myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Myfaces Wiki] Update of "Extensions/Validator/DevDoc" by GerhardPetracek
Date Mon, 02 Nov 2009 13:13:00 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Myfaces Wiki" for change notification.

The "Extensions/Validator/DevDoc" page has been changed by GerhardPetracek.
http://wiki.apache.org/myfaces/Extensions/Validator/DevDoc?action=diff&rev1=30&rev2=31

--------------------------------------------------

  = concept overview =
- 
  '''!!!this overview is not finished!!!'''
  
- hint to understand some concepts:
- extval introduces '''no''' requirement for annotations!
+ hint to understand some concepts: extval introduces '''no''' requirement for annotations!
  
  == startup ==
+ extval introduces so called startup-listener which are simple phase listener. a startup
listener is executed before restore view and de-registers itself after the init-method was
executed.<<BR>> so the logic of a startup-listener is called just once at the
very beginning of the jsf lifecycle (at the first lifecycle execution of the whole application).
- extval introduces so called startup-listener which are simple phase listener. a startup
listener is executed before restore view and de-registers itself after the init-method was
executed.<<BR>>
- so the logic of a startup-listener is called just once at the very beginning of the jsf
lifecycle (at the first lifecycle execution of the whole application).
  
+ implement a startup-listener:<<BR>> extend org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener<<BR>>
implement protected void init()
- implement a startup-listener:<<BR>>
- extend org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener<<BR>>
- implement protected void init()
  
- default convention:<<BR>>
- org.apache.myfaces.extensions.validator.custom.StartupListener
+ default convention:<<BR>> org.apache.myfaces.extensions.validator.custom.StartupListener
  
- use this convention within your webapp. if you provide e.g. a validation module as jar file
you can define the startup-listener within the faces-config of the module<<BR>>
+ use this convention within your webapp. if you provide e.g. a validation module as jar file
you can define the startup-listener within the faces-config of the module<<BR>>
(e.g. see: TrinidadModuleStartupListener)
- (e.g. see: TrinidadModuleStartupListener)
  
  the ExtValStartupListener registers the default ValidationInterceptor of the extval core
and executes org.apache.myfaces.extensions.validator.custom.StartupListener (if available)
  
@@ -29, +22 @@

  this factory type is the starting point of the extval mechanism. it's the result of several
concept iterations.
  
  old concepts (not used any more):
+ 
   * manually generated converters ... -> disadvantage: generate converters for all converters
used within the application
   * dynamically generated converters ... -> disadvantage: cglib dependency, restoring
the proxies due to a special serialization constellation
  
  new/current concept:
+ 
   * ExtValRenderKitFactory
  
  === ExtValRenderKitFactory ===
+ it decorates the original render-kit factory and delegates everything to the decorated factory.<<BR>>
furthermore, it adds the following behaviour to the getRenderKit method:
  
- it decorates the original render-kit factory and delegates everything to the decorated factory.<<BR>>
- furthermore, it adds the following behaviour to the getRenderKit method:
   * create a renderkit (delegation to the original factory)
   * get an implementation of AbstractRenderKitWrapperFactory<<BR>>(using: ''ExtValContext.getContext().getFactoryFinder().getFactory(FactoryNames.RENDERKIT_WRAPPER_FACTORY,
AbstractRenderKitWrapperFactory.class);'')
   * if the wrapper factory is deactivated the created renderkit is returned without a change
   * the wrapper factory creates a wrapper for the renderkit (created at the first step)
  
  === AbstractRenderKitWrapperFactory ===
- 
- it creates a wrapper for a given render-kit.<<BR>>
- the DefaultRenderKitWrapperFactory decorates the original render-kit with a new instance
of ExtValRenderKit
+ it creates a wrapper for a given render-kit.<<BR>> the DefaultRenderKitWrapperFactory
decorates the original render-kit with a new instance of ExtValRenderKit
  
  it's possible to add a custom implementation. if a custom implementation is available it
gets executed before the default implementation.
  
- adding a custom implementation:<<BR>>
+ adding a custom implementation:<<BR>> example:<<BR>>
- example:<<BR>>
+ 
  {{{
  ExtValContext.getContext().getFactoryFinder().getFactory(FactoryNames.RENDERKIT_WRAPPER_FACTORY,
AbstractRenderKitWrapperFactory.class).addRenderKitWrapperFactory(new CustomRenderKitWrapperFactory());
  }}}
  it's possible to add multiple factories. the factory which is added at the end is the first
factory which is invoked. if a factory returns a result it's used as final result. if it returns
null the next factory gets called.
  
  === ExtValRenderKit ===
+ it extends javax.faces.render.RenderKit<<BR>> it's the default wrapper implementation
and delegates everything to the wrapped render-kit. <<BR>> furthermore, it's responsible
to wrap renderer which are created by the original render-kit with the ExtValRendererWrapper.
- 
- it extends javax.faces.render.RenderKit<<BR>>
- it's the default wrapper implementation and delegates everything to the wrapped render-kit.
<<BR>>
- furthermore, it's responsible to wrap renderer which are created by the original render-kit
with the ExtValRendererWrapper.
  
  === ExtValRendererWrapper ===
- 
  it wraps the original renderer. internally it adds a proxy around the wrapped renderer.
this proxy should avoid duplicate calls of renderer methods.<<BR>>
  
  we need such a wrapper to allow:
+ 
   * no extra tags within the page
   * no required attribute within the page
   * component initialization based on metadata
+ 
  (implemented via renderer interceptors)
  
  === ExtValRendererProxy and RendererProxyEntry ===
- 
  it's a proxy for the original renderer which avoids multiple calls of the original renderer
method.
  
+ q: why is such a proxy essential?<<BR>> a: each renderer interceptor is able
to force the execution of the original renderer method at a specific point. the proxy avoids
further calls to the original renderer method. in case of getConvertedValue it's a performance
improvement (converted values are cached).
- q: why is such a proxy essential?<<BR>>
- a: each renderer interceptor is able to force the execution of the original renderer method
at a specific point. the proxy avoids further calls to the original renderer method. in case
of getConvertedValue it's a performance improvement (converted values are cached).
  
  if extval causes a wrong rendering behaviour, try to reset the proxy.<<BR>>
  
  to reset such a proxy use:<<BR>>
+ 
  {{{
  ExtValContext.getContext().addGlobalProperty(ExtValRendererProxy.KEY, null)
  }}}
@@ -92, +81 @@

  RendererProxyEntry is an internal request scoped data-structure which holds the information
which renderer method is already called (one entry per component instance)
  
  === renderer interceptor ===
+ it's possible to intercept method calls of the original renderer. you can add multiple interceptors.<<BR>>
you can register such an interceptor within a startup listener via:<<BR>>
  
- it's possible to intercept method calls of the original renderer. you can add multiple interceptors.<<BR>>
- you can register such an interceptor within a startup listener via:<<BR>>
  {{{
  ExtValContext.getContext().registerRendererInterceptor(new CustomValidationInterceptor());
  }}}
- 
  available methods:
+ 
   * beforeDecode, afterDecode
   * beforeEncodeBegin, afterEncodeBegin
   * beforeEncodeChildren, afterEncodeChildren
@@ -110, +98 @@

  
  AbstractRendererInterceptor is an internal convenience implementation which implements all
methods (except getInterceptorId) with an empty implementation. so it's possible to extend
it and just override the method you are interested in.
  
+ if beforeGetConvertedValue throws a SkipRendererDelegationException, getReturnValueOnException
of SkipRendererDelegationException is called.<<BR>> getReturnValueOnException
calls getReturnValueOnSkipRendererDelegationException of the renderer interceptor which threw
the exception. so it's possible to return an alternative result.
- if beforeGetConvertedValue throws a SkipRendererDelegationException, getReturnValueOnException
of SkipRendererDelegationException is called.<<BR>>
- getReturnValueOnException calls getReturnValueOnSkipRendererDelegationException of the renderer
interceptor which threw the exception. so it's possible to return an alternative result.
  
  (via exceptions it's possible to change the execution of renderer interceptors and the delegation
to the original renderer method)
  
- it's also possible to deregister or deny interceptors.<<BR>>
+ it's also possible to deregister or deny interceptors.<<BR>> to deregister means:
- to deregister means:
+ 
   * you know that an interceptor has been registered and you deregister it again.<<BR>>
  
  to deny means:
+ 
   * see deregister
   * the interceptor is added to a black list. if the interceptor is registered later on,
the registration process is skipped
  
  extval provides two implementations:
+ 
   * ValidationInterceptor (basic implementation)
   * ValidationInterceptorWithSkipValidationSupport
  
  ----
  
  == ValidationInterceptor ==
- 
  it's the default validation mechanism of the core.
  
  process of implemented mechanisms:
+ 
   * component initialization (beforeEncodeBegin)
+   * extract metadata
+   * check skipped validation (if it's the case -> skip initialization)
+   * transform metadata
+   * invoke all registered instances of ComponentInitializer
+  * validation (beforeGetConvertedValue)
+   * delegate ''getConvertedValue'' to the decorated renderer
+   * invoke all registered instances of ProcessedInformationRecorder (generic mechanism e.g.
used for cross-validation)
+   * process metadata based validation
     * extract metadata
-    * check skipped validation (if it's the case -> skip initialization)
-    * transform metadata
-    * invoke all registered instances of ComponentInitializer
-  * validation (beforeGetConvertedValue)
-    * delegate ''getConvertedValue'' to the decorated renderer
-    * invoke all registered instances of ProcessedInformationRecorder (generic mechanism
e.g. used for cross-validation)
-    * process metadata based validation
-      * extract metadata
-      * map current metadata entry to the validation strategy
+    * map current metadata entry to the validation strategy
-      * check skipped validation
+    * check skipped validation
-      * validate
+    * validate
  
  == ValidationInterceptorWithSkipValidationSupport ==
- 
  extends the basic implementation and adds the skip validation feature of the property-validation
module.
  
  == component initialization ==
- 
  a component initializer is responsible to initialize a component with the information provided
by the metadata of a bound value. it's used to join specific mechanisms of component libs.
  
  e.g.:
+ 
   * some input components are rendered with a visual indication, if they are required (typically
it's the: *)
   * join client-side validation of a component lib (see the extval-trinidad-support module)
  
- default convention:<<BR>>
- org.apache.myfaces.extensions.validator.custom.ComponentInitializer
+ default convention:<<BR>> org.apache.myfaces.extensions.validator.custom.ComponentInitializer
  
  via extval java api:<<BR>>
+ 
  {{{
  ExtValContext.getContext().addComponentInitializer(new CustomComponentInitializer());
  }}}
- 
  == metadata extractor ==
+ it's responsible to extract the metadata of a given object.<<BR>> an instance
of PropertyInformation is returned.
- 
- it's responsible to extract the metadata of a given object.<<BR>>
- an instance of PropertyInformation is returned.
  
  available implementations:
+ 
   * DefaultComponentMetaDataExtractor
   * DefaultPropertyScanningMetaDataExtractor
  
  === PropertyInformation ===
+ a data-structure which represents a property bound to an input component.<<BR>>
it's possible to get and set ''information'' for the property. such information are e.g. PropertyDetails
<<BR>> it's used internally to add PropertyDetails, however, it's possible to
add custom information via the same api.
- 
- a data-structure which represents a property bound to an input component.<<BR>>
- it's possible to get and set ''information'' for the property. such information are e.g.
PropertyDetails <<BR>>
- it's used internally to add PropertyDetails, however, it's possible to add custom information
via the same api.
  
  furthermore, it contains metadata entries. one metadata entry provides the information of
a specific annotation.
  
  === PropertyDetails ===
- 
  it contains basic information of a property:
+ 
   * a key which identifies the property (bean + property chain -- it's used for cross-validation)
   * baseObject (the base object of the target property)
   * property (the name of the target property)
  
  it's added during the metadata extraction process via:<<BR>>
+ 
  {{{
  propertyInformation.setInformation(PropertyInformationKeys.PROPERTY_DETAILS, propertyDetails);
  }}}
- 
  === MetaDataEntry ===
- 
- it contains a key (in case of annotations: package name + annotation name) and a value (any
object is possible - in case of annotations it's the annotation of the property).<<BR>>
- furthermore, it contains properties. the default implementation sets a reference to the
information map to these properties. so it's possible to access these information through
a metadata entry. that's not the cleanest approach, however, several concept iterations showed
that it's the easiest and cleanest approach to forward these information to the other mechanisms.
+ it contains a key (in case of annotations: package name + annotation name) and a value (any
object is possible - in case of annotations it's the annotation of the property).<<BR>>
furthermore, it contains properties. the default implementation sets a reference to the information
map to these properties. so it's possible to access these information through a metadata entry.
that's not the cleanest approach, however, several concept iterations showed that it's the
easiest and cleanest approach to forward these information to the other mechanisms.
  
  it's added during the metadata extraction process via <<BR>>
+ 
  {{{
  propertyInformation.addMetaDataEntry(createMetaDataEntryForAnnotation(annotation));
  }}}
- 
  === DefaultComponentMetaDataExtractor ===
+ it uses the el-helper to extract PropertyDetails of the target property.<<BR>>
furthermore, it adds a MetaDataEntry for each annotation of the property.<<BR>>
the annotations of:
  
- it uses the el-helper to extract PropertyDetails of the target property.<<BR>>
- furthermore, it adds a MetaDataEntry for each annotation of the property.<<BR>>
- the annotations of:
   * property
-    * get[Property-name]()
+   * get[Property-name]()
-    * is[Property-name]()
+   * is[Property-name]()
   * field
-    * [property-name]
+   * [property-name]
-    * _[property-name]
+   * _[property-name]
  
  === skip validation support ===
+ the ValidationInterceptor of the core prepares the skip validation feature. ValidationInterceptorWithSkipValidationSupport
implements this feature for the property-validation module. that means that the ValidationInterceptor
of the core gets deactivated if the property-validation module is used. within the startup
listener of the property-validation module it's done via:
  
- the ValidationInterceptor of the core prepares the skip validation feature. ValidationInterceptorWithSkipValidationSupport
implements this feature for the property-validation module.
- that means that the ValidationInterceptor of the core gets deactivated if the property-validation
module is used.
- within the startup listener of the property-validation module it's done via:
  {{{
  ExtValContext.getContext().denyRendererInterceptor(ValidationInterceptor.class);
  ExtValContext.getContext().registerRendererInterceptor(new ValidationInterceptorWithSkipValidationSupport());
  }}}
- 
  since extval follows the principle that there's no requirement for annotations the validation
strategy has to provide the information. annotate the validation strategy class with @SkipValidationSupport,
if it should be possible to skip the validation via @SkipValidation. if a condition of @SkipValidation
is true all following skip-able validation strategies (and also metadata transformer) are
skipped.
  
- implementation details:
- @SkipValidation also has a validation strategy. if the condition is true the strategy adds
an information to the current metadata entry that the validation of further annotations should
be skipped (if supported). that works because all metadata entries for a property share the
same information (of the property). so this information is available for all following validations.
+ implementation details: @SkipValidation also has a validation strategy. if the condition
is true the strategy adds an information to the current metadata entry that the validation
of further annotations should be skipped (if supported). that works because all metadata entries
for a property share the same information (of the property). so this information is available
for all following validations.
  
  === MetaDataExtractionInterceptor ===
  (since 1.x.2)
  
+ to get a better performance for the jsr 303 integration this type of interceptor was introduced.<<BR>>
e.g. in case of xml configured class based validation it isn't required to have an annotation
in place. so such an interceptor has to add the information provided by xml configs to the
PropertyInformation object.<<BR>> the alternative (without changes) would be an
additional renderer-interceptor (this would lead to double extraction for each property).
furthermore, MetaDataExtractionInterceptors allows the core to be independent of jsr 303 mechanisms.
moreover, it also allows similar 3rd party mechanisms.
- to get a better performance for the jsr 303 integration this type of interceptor was introduced.<<BR>>
- e.g. in case of xml configured class based validation it isn't required to have an annotation
in place. so such an interceptor has to add the information provided by xml configs to the
PropertyInformation object.<<BR>>
- the alternative (without changes) would be an additional renderer-interceptor (this would
lead to double extraction for each property). furthermore, MetaDataExtractionInterceptors
allows the core to be independent of jsr 303 mechanisms. moreover, it also allows similar
3rd party mechanisms.
  
  adding a custom implementation:
+ 
  {{{
  ExtValContext.getContext().addMetaDataExtractionInterceptor(new CustomMetaDataExtractionInterceptor());
  }}}
- 
  == MetaDataTransformer ==
- 
  it's responsible for unifying the metadata information. e.g. @Column(nullable = false);
@Required; Length(minimum = 1);... express that the field is required. so this information
is distilled to a generic form. this generic form is used by component-initializers to initialize
a component (based on metadata-information).
  
  == ProcessedInformationRecorder ==
- 
  it provides the possibility to register recorders which record the converted object of a
component. it's the first step of cross-validation (see: CrossValidationUserInputRecorder).
  
  to register a custom recorder use:
@@ -259, +230 @@

  {{{
  ExtValContext.getContext().addProcessedInformationRecorder(new CustomUserInputRecorder());
  }}}
- 
  == ValidationStrategy ==
+ it's the base interface which is used by the ValidationInterceptor. since we hooked in the
conversion we have to throw a ConverterException instead of a ValidatorException.<<BR>>
that wouldn't be nice. so all extval validation strategies extend the AbstractValidationStrategy
which translates ValidatorExceptions to ConverterExceptions.
- 
- it's the base interface which is used by the ValidationInterceptor. since we hooked in the
conversion we have to throw a ConverterException instead of a ValidatorException.<<BR>>
- that wouldn't be nice. so all extval validation strategies extend the AbstractValidationStrategy
which translates ValidatorExceptions to ConverterExceptions.
  
  it isn't called ''validator'' to avoid confusions. jsf provides validators, bean validation
(jsr 303) also provides validators. so it would be confusing to have 3 kinds which are called
''validator''.
  
@@ -272, +240 @@

  to build a custom validation infrastructure it's possible to register a custom RendererInterceptor.
so it's possible to reuse the core mechanism and design a custom infrastructure.
  
  == MessageResolver ==
- 
  per default validation strategies reuse the jsf validation messages. anyway, extval provides
much more. out-of-the-box several default validation strategies use the message resolver mechanism
which uses ''validationErrorMsgKey'' of an annotation to resolve the internationalized message
for a given key. if there's no value for the key, the equivalent jsf message is used (if possible).
  
  the default implementation uses message bundles. anyway, it's possible to provide an implementation
for any data source.
  
  it's possible to provide a message resolver per:
+ 
   * validation strategy
   * validation module
  
  furthermore, for custom validation strategies it's possible to inject a central message
resolver of the application via dependency injection.
  
  == ValidationExceptionInterceptor ==
- 
  with validation strategies which extend AbstractValidationStrategy or CrossValidationStrategy
it's possible to intercept ValidatorExceptions.
  
- default convention:<<BR>>
- org.apache.myfaces.extensions.validator.custom.ValidationExceptionInterceptor
+ default convention:<<BR>> org.apache.myfaces.extensions.validator.custom.ValidationExceptionInterceptor
  
  ----
  
  == ExtValContext ==
- 
  it's the central application scoped context to get/add/remove implementations of different
mechanisms.
  
  ----
  
  == factories ==
- 
  extval uses several factories. furthermore, it's possible to provide custom implementations.
all factories are resolved via the FactoryFinder
  
  === ClassMappingFactory ===
- 
  it's the central interface for mapping one class to an other one. the default implementations
use the name mapping concept.
  
  == name mapping ==
- 
  this concept is used to implement different name conventions. a name of an artifact is mapped
to a name of an other artifact. via custom name mappers it's possible to provide custom implementations
of name mappers.
  
  == StaticConfiguration ==
- 
  it's possible to register static configurations for several mechanisms at the startup. the
default implementations of factories cache the mapping. at the first call a factory adds the
static configs to the internal cache.
  
  ----
  
  == storages ==
+ this concept allows to implement storages with different scopes and functionality but a
generic mechanism to manage them.<<BR>> developers can resolve and reset storages
via a generic api. to identify a storage a storage-type and storage-name is required. so it's
possible to have multiple storages with the same type.
- 
- this concept allows to implement storages with different scopes and functionality but a
generic mechanism to manage them.<<BR>>
- developers can resolve and reset storages via a generic api. to identify a storage a storage-type
and storage-name is required. so it's possible to have multiple storages with the same type.
  
  e.g. the GroupStorage is request scoped and the MetaDataStorage is application scoped furthermore
both have a different functionality.
  
  resolve a storage:
+ 
  {{{
  public <T> T getStorage(Class<T> storageType, String storageName)
  {
@@ -331, +291 @@

  }
  }}}
  reset a storage:
+ 
  {{{
  public void resetStorage(Class storageType, String storageName)
  {
@@ -338, +299 @@

  }
  }}}
  resolve the storage manager factory:
+ 
  {{{
  private static ClassMappingFactory<Class, StorageManager> getStorageManagerFactory()
  {
@@ -348, +310 @@

  the storage manager factory works via the name-mapper mechanism of extval. it allows to
map a storage type to the storage manager.
  
  === StorageManager ===
+ a storage manager gets registered in the factory and mapped to the type. it is responsible
to manage multiple storages of the same type. furthermore, it allows to create and reset a
storage with a specific name.<<BR>> storage manager implementations provide a
key which allows to store the storages via an internal key. storage managers can also use
name mappers to map from the storage interface to the storage implementation
- a storage manager gets registered in the factory and mapped to the type. it is responsible
to manage multiple storages of the same type. furthermore, it allows to create and reset a
storage with a specific name.<<BR>>
- storage manager implementations provide a key which allows to store the storages via an
internal key. storage managers can also use name mappers to map from the storage interface
to the storage implementation
  
  === StorageManagerHolder ===
  allows to get and set storage managers for a given type. it's a factory to create storage
managers (factory name: STORAGE_MANAGER_FACTORY)
  
  === implementing a new storage ===
   * storage interface with specific storage api (each storage type has a different api)
+ 
  {{{
  public interface MyStorage
  {
@@ -367, +329 @@

  }}}
   * storage implementation
   * storage manager implementation (to provide a key to cache storages of the same type in
a given scope)
+ 
  {{{
  //there are already implementations for request and application scoped storage implementations
  //which extend a generic implementation (AbstractStorageManager) which uses the name mapper
concept
@@ -384, +347 @@

  }
  }}}
   * name mapper (storage interface to storage implementation) – if a storage manager implementation
requires it
+ 
  {{{
  public class MyNameMapper implements NameMapper<String>
  {
@@ -394, +358 @@

  }
  }}}
   * use it
+ 
  {{{
  //1. arg: storage type 2. arg: storage name
  ExtValUtils.getStorage(MyStorage.class, "st1").add(...);
@@ -403, +368 @@

  ExtValUtils.getStorage(MyStorage.class, "st1").getO1(...);
  }}}
   * reset it
+ 
  {{{
  ExtValUtils.resetStorage(MyStorage.class, "st1");
  }}}
@@ -411, +377 @@

  StorageManagerHolder storageManagerHolder = (ExtValContext.getContext().getFactoryFinder()
    .getFactory(FactoryNames.STORAGE_MANAGER_FACTORY, StorageManagerHolder.class));
  }}}
- 
  === register custom storage managers ===
  {{{
  storageManagerHolder.setStorageManager(MyStorage.class, new MyStorageManager(), true);
  }}}
- 
  ----
  
  == conventions ==
- 
  conventions (e.g. name mapping) are used to allow zero configuration. configuration is just
optional and overrules conventions.
  
  list of conventions:
+ 
   * within the custom base package (also the custom base package is customizable)
-    * StartupListener
+   * StartupListener
-    * ComponentMetaDataExtractor
+   * ComponentMetaDataExtractor
-    * ComponentInitializer
+   * ComponentInitializer
-    * ValidationExceptionInterceptor
+   * ValidationExceptionInterceptor
-    * name mapper
+   * name mapper
-      * ValidationStrategyToMsgResolverNameMapper
+    * ValidationStrategyToMsgResolverNameMapper
-      * MetaDataToValidationStrategyNameMapper
+    * MetaDataToValidationStrategyNameMapper
-      * ValidationStrategyToMetaDataTransformerNameMapper
+    * ValidationStrategyToMetaDataTransformerNameMapper
-    * factories
+   * factories
-      * MessageResolverFactory
+    * MessageResolverFactory
-      * ValidationStrategyFactory
+    * ValidationStrategyFactory
-      * ComponentMetaDataExtractorFactory
+    * ComponentMetaDataExtractorFactory
-      * MetaDataTransformerFactory
+    * MetaDataTransformerFactory
-    * resource bundles
+   * resource bundles
-      * custom message bundle name
+    * custom message bundle name
-      * custom resource bundle name for static metadata-key -> validation strategy mapping
+    * custom resource bundle name for static metadata-key -> validation strategy mapping
   * postfix for name mapping
-    * ValidationStrategy
+   * ValidationStrategy
-    * MetaDataTransformer
+   * MetaDataTransformer
-    * ValidationErrorMessageResolver
+   * ValidationErrorMessageResolver
  
  == InformationProviderBean ==
- 
  it's the central mechanism to customize conventions.
  
  ----
  
  == el-helper ==
- 
  it's a pluggable mechanism to get PropertyDetails, ... of the bound property and other el
topics used by extval.
  
  setting a custom el-helper via a startup-listener (a short example)
@@ -475, +437 @@

      }
  }
  }}}
- 
  if you have to provide a completely new impl., you can also use the interface of the el-helper
(org.apache.myfaces.extensions.validator.core.el.ELHelper)
+ 
  ----
  
  == jsr 303 integration ==
@@ -485, +447 @@

  the current goal of this myfaces extval validation-module is to use bean validation (jsr
303) constraints with all jsf versions (1.x and 2.x).
  
  === structure ===
- 
  the bean validation (jsr 303) integration is an optional validation module for extval
  
  part of the current structure + the new validation module (validation-modules/'''bean-validation'''):<<BR>>
+ 
  {{{
  |___component-support
  |   |___generic-support
@@ -498, +460 @@

      |___bean-validation
      |___property-validation
  }}}
- 
  === group validation (partial validation) ===
+ jsr 303 specifies group validation. it means that only the constraints which match a given
group are validated.<<BR>> so you can call it "partial validation". details are
available [[http://relation.to/10416.lace|here]].
- jsr 303 specifies group validation. it means that only the constraints which match a given
group are validated.<<BR>>
- so you can call it "partial validation". details are available [[http://relation.to/10416.lace|here]].
  
+ jsf 2.0 integrates bean validation via tags<<BR>> e.g.: <f:validateBean validationGroups="javax.validation.groups.Default,app.validation.groups.Order"/><<BR>>
first of all it's quite a lot to type the fully qualified class name within a page.<<BR>>
myfaces-core 2 has to impl. this tag, because it's part of the spec.<<BR>>
- jsf 2.0 integrates bean validation via tags<<BR>>
- e.g.: <f:validateBean validationGroups="javax.validation.groups.Default,app.validation.groups.Order"/><<BR>>
- first of all it's quite a lot to type the fully qualified class name within a page.<<BR>>
- myfaces-core 2 has to impl. this tag, because it's part of the spec.<<BR>>
  
- myfaces extval is able to provide an alternative approach.<<BR>>
- extval provides a generic api which looks like:
+ myfaces extval is able to provide an alternative approach.<<BR>> extval provides
a generic api which looks like:
+ 
  {{{
  ExtValBeanValidationContext.getCurrentInstance().addGroup(...)
  }}}
+ so it's possible to provide different approaches to define groups which have to be added
to this context.<<BR>> it would be possible via a tag. anyway, to reduce the complexity
of pages extval provides annotations for it.
  
+ first of all - partial validation shouldn't be used extensively to avoid too complex pages.<<BR>>
the annotaton approach is similar to the view-controller annotation of orchestra.
- so it's possible to provide different approaches to define groups which have to be added
to this context.<<BR>>
- it would be possible via a tag. anyway, to reduce the complexity of pages extval provides
annotations for it.
- 
- first of all - partial validation shouldn't be used extensively to avoid too complex pages.<<BR>>
- the annotaton approach is similar to the view-controller annotation of orchestra.
  
  the idea is to annotate page beans and/or their properties
  
  ==== default group handling ====
  per default every page is validated with the default group (javax.validation.groups.Default).
so you don't really need example 1 and 2.<<BR>>
+ in case of group validation the default group has to be declare explicitly and so example
1 and 2 make sense again to re-add the default group automatically for the given scenarios.
that means: normally you don't need to use @BeanValidation explicitly. jsr 303 constraints
have the default group (javax.validation.groups.Default) per default :). so the default group
(javax.validation.groups.Default) is validated implicitly. if you want to validate 1-n groups
and also the default group, you can add the @BeanValidation annotation as class level annotation
instead of listing the default group side by side with the other groups.
- there will be a context-param to deactivate this default behavior. in such cases example
1 and 2 make sense again.
- 
- that means:<<BR>>
- normally you don't need to use @BeanValidation explicitly. jsr 303 constraints have the
default group (javax.validation.groups.Default) per default :). so the default group (javax.validation.groups.Default)
is validated implicitly. if you validate with a given group, the default group is deactivated.
just if you would like to add or restrict groups for all or for a specific view-id you have
to use @BeanValidation.
  
  ==== usage ====
- the following examples are available [[http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/|here]]<<BR>>
+ the following examples are available [[http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/|here]]<<BR>>
they are based on the hello world application of myfaces.<<BR>>
- they are based on the hello world application of myfaces.<<BR>>
  
  example 1:
+ 
  {{{
+ //adds the default group in all cases of group validation
  @BeanValidation
  public class HelloWorldController {...}
  }}}
- 
- ... that means:<<BR>>
- the default group (javax.validation.groups.Default) is used for all pages which are using
this page bean.
+ ... that means:<<BR>> the default group (javax.validation.groups.Default) is
used for all pages which are using this page bean.
  
  example 2:
+ 
  {{{
  public class HelloWorldController
  {
@@ -551, +502 @@

  ...
  }
  }}}
+ ... that means:<<BR>> the default group (javax.validation.groups.Default) is
used just for view-id form1.jsp<<BR>> (if there is also an annotation at the class
(see example 1) both information get added to the context.)
- 
- ... that means:<<BR>>
- the default group (javax.validation.groups.Default) is used just for view-id form1.jsp<<BR>>
- (if there is also an annotation at the class (see example 1) both information get added
to the context.)
  
  example 3:
+ 
  {{{
  public class HelloWorldController
  {
@@ -565, +514 @@

  ...
  }
  }}}
- 
- ... that means:<<BR>>
- the User group is used to validate every expression which uses the person property of the
hello world controller bean.<<BR>>
+ ... that means:<<BR>> the User group is used to validate every expression which
uses the person property of the hello world controller bean.<<BR>>
  
  example 4:
+ 
  {{{
+ @BeanValidation(viewIds = "/form1.jsp")
  public class HelloWorldController
  {
      private Person person = new Person();
  
      @BeanValidation.List({
-             @BeanValidation(viewIds = "/helloWorld.jsp"),
              @BeanValidation(viewIds = "/form1.jsp", useGroups = User.class),
              @BeanValidation(viewIds = "/form2.jsp", useGroups = Admin.class)
      })
@@ -587, +535 @@

  ...
  }
  }}}
+ ... that means:<<BR>> the default group (javax.validation.groups.Default) as
well as the User group is used to validate form1.jsp if the value-binding uses the page-bean<<BR>>
the Admin group is used to validate form2.jsp
- 
- ... that means:<<BR>>
- the default group (javax.validation.groups.Default) is used for helloWorld.jsp<<BR>>
- the User group is used to validate form1.jsp<<BR>>
- the Admin group is used to validate form2.jsp
  
  ==== possible/logical targets ====
   * page bean class
@@ -599, +543 @@

   * last base of the bound property
   * the bound property
  
- ... that means:<<BR>>
- #{pageBean.pageBeanProperty.property1.property2.propertyBase.property}
+ ... that means:<<BR>> #{pageBean.pageBeanProperty.property1.property2.propertyBase.property}
  
  in this example the >possible< targets are:
+ 
   * pageBean
   * pageBeanProperty
   * propertyBase (in most szenarios this target isn't suggested)
   * property (in most szenarios this target isn't suggested)
  
+ summarized:<<BR>> it's possible to annotate the first bean of an expression,
its properties as well as the last base and the final property.<<BR>> that means:
extval scans these logical targets (including super-classes and interfaces) and all levels
in between are skipped.
- summarized:<<BR>>
- it's possible to annotate the first bean of an expression, its properties as well as the
last base and the final property.<<BR>>
- that means: extval scans these logical targets (including super-classes and interfaces)
and all levels in between are skipped.
  
  ==== comments ====
  @BeanValidation.List is the jsr 303 style for constraints
  
  === conditional validation ===
- 
  example 1:
+ 
  {{{
  @BeanValidation(viewIds = "/form1.jsp", useGroups = User.class, conditions = "#{person.role
eq 'admin'}")
  }}}
- 
- ... that means:<<BR>>
- it's only validated if at least one condition returns true.
+ ... that means:<<BR>> it's only validated if at least one condition returns
true.
+ 
+ === restricted groups ===
+ example 1:
+ {{{
+ @BeanValidation(viewIds = "/form1.xhtml", useGroups = {User.class, Address.class})
+ public class HelloWorldController
+ {
+     @BeanValidation(viewIds = "/form1.xhtml", restrictGroups = User.class, conditions =
"#{person.role eq 'admin'}")
+     private Person person = new Person();
+ }
+ }}}
+ ... that means:<<BR>> if this pagebean is used in a value-binding in page form1.xhtml
the User and Address group is used for validation. if a(n) in-/direct property of person is
the target of the value-binding in page form1.xhtml and the condition returns true the User
group isn't used for validation.
  
  === model validation ===
+ it's possible to activate model validation as well (validation after the "update model values"
phase).<<BR>> if activated, the last base of the bound property is validated.<<BR>>
in case of the example-binding<<BR>> #{pageBean.pageBeanProperty.property1.property2.propertyBase.property}<<BR>>
the object of '''propertyBase''' gets validated per default. all you have to do is to add
the @ModelValidation.<<BR>> optionally you can provide one or more custom target(s)
via a conventional el-binding.<<BR>> per default the validation error messages
are displayed via the messages component (e.g. h:messages). if it makes sense, you can display
also these model-validation error messages at the component which triggered the model validation
process of the object. (to be correct: the message component for the input-component which
triggered the model validation.)
- it's possible to activate model validation as well (validation after the "update model values"
phase).<<BR>>
- if activated, the last base of the bound property is validated.<<BR>>
- in case of the example-binding<<BR>>
- #{pageBean.pageBeanProperty.property1.property2.propertyBase.property}<<BR>>
- the object of '''propertyBase''' gets validated per default. all you have to do is to add
the @ModelValidation.<<BR>>
- optionally you can provide one or more custom target(s) via a conventional el-binding.<<BR>>
- per default the validation error messages are displayed via the messages component (e.g.
h:messages). if it makes sense, you can display also these model-validation error messages
at the component which triggered the model validation process of the object. (to be correct:
the message component for the input-component which triggered the model validation.)
  
- in comparison to field based validation, model validation works a bit different.<<BR>>
- each @ModelValidation is processed independently whereas information of multiple @BeanValidation
for field based validation are merged.
+ in comparison to field based validation, model validation works a bit different.<<BR>>
each @ModelValidation is processed independently whereas information of multiple @BeanValidation
for field based validation are merged.
  
  example 1:
+ 
  {{{
  @BeanValidation(useGroups = Address.class, modelValidation = @ModelValidation(isActive =
true))
  }}}
- 
- ... that means:<<BR>>
- after the field based bean-validation (jsr 303) validation of all bound properties (in the
"process validations" phase), the model is updated by jsf. afterwards model-validation for
the address group is executed.
+ ... that means:<<BR>> after the field based bean-validation (jsr 303) validation
of all bound properties (in the "process validations" phase), the model is updated by jsf.
afterwards model-validation for the address group is executed.
  
  example 2:
+ 
  {{{
  @BeanValidation.List({
          @BeanValidation(viewIds = "/form1.jsp", useGroups = Admin.class),
@@ -653, +598 @@

                  modelValidation = @ModelValidation(isActive = true))
  })
  }}}
- 
- ... that means:<<BR>>
- field based validation on page form1.jsp is performed with the admin group and model validation
for the same page is performed with the address group.
+ ... that means:<<BR>> field based validation on page form1.jsp is performed
with the admin group and model validation for the same page is performed with the address
group.
  
  example 3:
+ 
  {{{
  @BeanValidation(useGroups = Address.class, modelValidation = @ModelValidation(isActive =
true, displayInline = true))
  }}}
- 
- ... that means:<<BR>>
- it's like example 1. in contrast to example 1 the validation error messages are displayed
inline (at the message component of the component which triggered the model validation)
+ ... that means:<<BR>> it's like example 1. in contrast to example 1 the validation
error messages are displayed inline (at the message component of the component which triggered
the model validation)
  
  example 4:
+ 
  {{{
  @BeanValidation(useGroups = Address.class,
          modelValidation = @ModelValidation(isActive = true, validationTargets = "#{registrationPage.person.address}"))
  }}}
- 
- ... that means:<<BR>>
- instead of validating the last base (the '''propertyBase''' of the previous binding-example),
the address object of the "current" person gets validated.
+ ... that means:<<BR>> instead of validating the last base (the '''propertyBase'''
of the previous binding-example), the address object of the "current" person gets validated.
  
  example 5:
  {{{
  @BeanValidation(useGroups = Address.class,
        modelValidation = @ModelValidation(isActive = true, message = "address is required"))
  }}}
- 
- ... that means:<<BR>>
- the validation might lead to multiple validation error messages. if it's required to display
a single message which summarizes the validation error, it's possible to override the original
validation error messages.
+ ... that means:<<BR>> the validation might lead to multiple validation error
messages. if it's required to display a single message which summarizes the validation error,
it's possible to override the original validation error messages.
  
  === dev-demos ===
  [[attachment:myfaces_extval_jsr303_demo-alpha1.zip]]
@@ -689, +628 @@

  ----
  
  = drafts =
- [[/Drafts|Drafts for new features]]
+ [[Extensions/Validator/DevDoc/Drafts|Drafts for new features]]
  
  = steps for a release =
+ [[Extensions/Validator/DevDoc/Steps_For_A_Release|release steps]]
  
- [[/Steps_For_A_Release|release steps]]
- 

Mime
View raw message