Generating Application UI from Dynamic Data
Recently we've been asked by multiple customers how they can dynamically control the generation of forms and views based on some data that is determined at runtime.
For example, here are a couple of slightly different scenarios we've been asked about:
- How can I use runtime metadata to control all the rich behavior of form fields, including things like formatting, validation, visibility, UI type (drop-down vs text field vs radio buttons, etc.)?
- How can I create a single application model that generates many different variations based on data structures that are defined at runtime, for example in a database containing metadata describing the fields for the application?
Developers familiar with Web Experience Factory have seen that application UI is typically built at design time using a schema-driven approach. The schema is used to generate a set of page fields, and the Data Field Settings builder or Rich Data Definition builder can then control all the field behavior. For the scenarios above, in order to change the inputs that control this code generation at runtime, you need to use the profiling feature of Web Experience Factory. For portlets, you can tie profiling to portlet preferences which are configured at runtime in the Edit, Edit Shared Settings, and Configure modes. But what may not be obvious is how you can get profile data dynamically at runtime from some other data source, for example from a database or web service.
The answer is with a Profile Values Handler. When you edit a Profile Set, one of the tabbed screens is for "Select Handler." Here you can specify a "Value Setter" Java class that will be called to determine all the profile values for a profile set. Whenever a model is first executed in a session, the Factory engine will call your handler to get the profile values before the model is regenerated.
There's one more useful feature available when implementing this. The Profile Values Handler is a Java class, but suppose you'd like to use some of the Web Experience Factory connectors to retrieve your profile data. For this, you can actually call a Method or Action List in any model from your handler. To do this, use the ModelInstanceCreator object that's passed into your handler to obtain a WebAppAccess object for any model (but not the model that's profiled). Then you can call any method in the model. The method you call should return the profile data, typically String or IXml. It's that simple! In the model you're calling from your handler, you can use any data access builders such as the SQL builders or the REST or Web service builders.
With this mechanism in place, you can use profiling however you want in your models. For scenario #1 above, you would probably have a single profile entry containing a chunk of XML data, and you would use the data to drive an XML input of Rich Data Definition or Data Field Settings. Scenario #2 is more complex, since you have to profile the builder inputs that control the schema generation. In other scenarios you might profile a number of individual String values, using the profile entry name to locate values in your database for example.
We don't yet have a complete sample of these techniques posted on the wiki, but there is a sample showing a profile values handler that gets profile values from a properties file. See below for a link to this sample, which also shows how you can select a profile name from a properties file. This sample could be easily modified to retrieve profile values by calling an action in another model using ModelInstanceCreator.
Hopefully this gives a high-level picture of how you can leverage the flexibility and extensibility of the Web Experience Factory engine in order to implement some very dynamic code generation scenarios. From the very first release of the product, we've tried to make sure that the code generation framework is very extensible and flexible so that you can adapt it to all sorts of needs.