The Java Object Validation Framework
Download (SourceForge Hosted)
Accessing iScreen: Using the Factory
iScreen uses a factory approach to gaining access to services provided by the engine. These services are backed by a set of configuration files (one or more).
There are two basic approaches to using the factory API. Both cases assume that an IoC Container are not being used (or, if they are being used, it's the IoC Container that's using these APIs). These two approaches are as follows:
Direct Factory Calls
Though not recommended, the fundamental way in which to gain access to iScreen services is via a direct call to the factory API. This is done by calling a org.iscreen.ValidationFactory static method:
ValidationFactory factory; factory = ValidationFactory.buildFactory( ValidationFactory.FACTORY_OGNL_XML, "location/of/config/file", mapOfServices );
The first parameter defines the configuration file format (including which library to use: either OGNL or MVEL). To use MVEL, use the constant ValidationFactory.FACTORY_MVEL_XML (note that OGNL is the default). The second parameter is the location of the root configuration file. It is based upon the classpath (so the configuration file can be embedded within the application's JAR file). The final parameter is a java.util.Map of external services that the configuration file requires. The final map can be null.
Once the factory is constructed, access to a particular ValidationService requires the unique id of the ValidationSet (from the configuration file).
ValidationService service = factory.getValidationService( "full.namespace.of.ValidationSet" );
Another approach is to use meta data about the validation service. Assuming that you associate one or more meta tags against a validation set in the configuration file, you can access that validation service without knowing its id. You use a combination of the meta property name (such as "className") and the meta value, itself.
A common example is to add the class name of the JavaBean that is validated by
a particular validation set:
<validation-set id="someId"> <meta>com.mypackage.myBean</> </validation-set>
In this example, we use the default property name (className), so there's no "property" attribute on the meta tag. To get the validation service for this validation set:
ValidationService service = factory.getValidationService( "className", "com.mypackage.myBean" );
Where this becomes interesting is replacing the second parameter ("com.mypackage.myBean") with something like: bean.getClass().getName(). This will effectively remove the need to keep track of which validation service goes to which bean.
Note that multiple meta tags can be associated with a validation service. They also don't have to be unique, so it's possible that you could get multiple validation services using the above code. The implementation of the ValidationService returned is actually a container for zero or more actual ValidationService implementations. This means that when you call validate(), it's called on all contained ValidationServices.
JavaBean Factory Calls
The preferred method (when not using an IoC Container) to get access to iScreen's services is to use the JavaBean Factory approach. The reason for this is that it's easier.
In either approach, the factory needs to know the type of configuration file, the location of the configuration file, and any special services that custom-built Validators may require (more on that later). In addition, you can choose the base locale that the factory will use for selecting localized messages.
The JavaBean Factory approach is simpler because the JavaBean doesn't require all of the above information, as it will use defaults for all but one parameter. The only required parameter is the location of the root configuration file (we use the term 'root configuration file' because a configuration file may reference other configuration files; the factory needs to see the 'outermost' configuration file...or the 'root').
The configuration format type defaults to OGNL XML, so it is not required; the Map of services is also not required, because it may not be necessary; the locale is not required, because it defaults to the system's default locale. So, to construct this JavaBean, create an instance of the org.iscreen.ValidationFactoryConfig class as follows:
ValidationFactoryConfig factory = new ValidationFactoryConfig( "location/of/config/file" );
Additional constructors are available if you need to provide additional information. In addition, setters are available for making changes once it's constructed.
Technically, the above approach won't construct the actual factory. To do that, call the JavaBean's getFactory() method. However, this is not necessary if you use the org.iscreen.ValidationServiceWrapper class to access the actual ValidationService (the ValidationServiceWrapper is an implementation of the ValidationService interface). In that case, you merely construct it like this:
ValidationServiceWrapper service = new ValidationServiceWrapper( factory, "full.namespace.of.ValidationSet" );
In addition, support for the meta data tags have been added to the factory configuration class. See the JavaDoc for details.
Sometimes, when creating your own custom Validators, you'll need to pass external services that the Validator requires (i.e. DataSource for database access; JNDI; etc.). These external services are set on the Validator once when it is created. The configuration file specifies how this is done, but the actual service is pushed through to the Validator via the factory. These services require a unique id that's referenced both in the configuration file and by a map entry in the factory.
For example, if you use the id of 'globalDatasource' as the name for a DataSource object so that your Validator can access a particular database, then you could use the following code to add that map entry to a factory:
javax.sql.DataSource myDatasource; //get reference to datasource from JNDI //... ValidationFactoryConfig factory = new ValidationFactoryConfig( "location/of/config/file" ); factory.addService( "globalDatasource", myDatasource );
IoC Container Integration
When configuring access to iScreen services within an IoC Container, use the JavaBean Factory approach, as it supports both constructor-based and setter-based dependency injection.
For a guide on how to use Spring, see the Spring Quick Guide.