As jZeno screens can become very complex, the number of components on a single screen can grow to a relatively large number. In general jZeno promotes a more pure OO approach to designing your application. One of the effects of this is that creation times for components, screens and perhaps other (application specific) objects can become a performance bottleneck if handled in a na�ve fashion.
To avoid delays on user interactions jZeno has a simple object factory, called the FastFactory. It is the responsability of this factory to speed up object creation. The FastFactory does this in 2 ways :
To take advantage of this mechanism applications can use the factory methods on EchoSupport (create(), createPropertyComponent(), etc...). Internally jZeno obviously takes advantage of this (The MenuBar for example, as well as the DynaTable component). But your application code can also use these factory methods to speed up object creation.
One disadvantage of this technique is that object creation is going to happen outside of the normal (security,HTTP request,etc..) context. Therefore your objects should not refer to either SecuritySupport, or ServletSupport. In order to indicate that you are conscious of this restriction you have to make your class implement the Precreation interface. If your object does require fine-tuning based on the security and/or servlet context, you can do this in the applyContext() method, that is mandated by this interface. This method will get called on your object by the FastFactory, when a new instance is requested.
public class PrefixEditor extends CustomComponent implements EventPropagator, Precreation { private final static long serialVersionUID = 1L; private boolean limitToAssignedPrefixes = true; private DynaSelectField dynaSelectField = null; public PrefixEditor() { this(null, null, null); } public PrefixEditor(Class beanClass, String property, String constructionHints) { super(beanClass, property, ""); dynaSelectField = new DynaSelectField(getClass(), "prefix", "width=-1"); dynaSelectField.setLabelProperty("code"); add(dynaSelectField); EchoSupport.executeHints(this, constructionHints); applyContext(); } public void applyContext() { if (FastFactory.isInsideContext()) { refreshList(); } } /************************************************************/ /** !! This method does context sensitive initialisation !! */ /************************************************************/ public void refreshList() { List list = new ArrayList(); if (isLimitToAssignedPrefixes()) { if (((User) SecuritySupport.getCurrentUser()).getPrefixes().size() == 0) { list = BusinessCache.getAllPrefixesCached(); } else { list = new ArrayList(((User) SecuritySupport.getCurrentUser()).getPrefixes()); } } else { list = BusinessCache.getAllPrefixesCached(); } dynaSelectField.setList(list); } public boolean isLimitToAssignedPrefixes() { return limitToAssignedPrefixes; } public void setLimitToAssignedPrefixes(boolean limitToAssignedPrefixes) { this.limitToAssignedPrefixes = limitToAssignedPrefixes; if(FastFactory.isInsideContext()) refreshList(); } public void setPrefix(Prefix prefix) { setValue(prefix); } public Prefix getPrefix() { return (Prefix) getValue(); } public void setActionCommand(String actionCommand) { dynaSelectField.setActionCommand(actionCommand); } public String getActionCommand() { return dynaSelectField.getActionCommand(); } public void propagateEvent(ActionEvent event) { fireActionEvent(event.getActionCommand()); } }
Note the refreshList() method that calls the SecuritySupport class. This method would normally be called directly from the constructor, but as we want our object to be pre-created, we need to call it from the applyContext method.
If your class will be created via the FastFactory as well as through a regular cunstruction call, you need to take into account that applyContext is normally only called by the Factory. So how can you make sure that the context-sensitive initialisation get executed in both scenarios ?
In the example above this problem is solved by calling applyContext directly from the constructor. You can then avoid double execution by guarding the applyContext() method to only execute when the object is not being pre-created (and hence being created 'in-context'). Use FastFactory.isInsideContext() for this purpose as shown above.
This pattern also gives you a clear migration path if your code has a lot of components that do not implement Precreation.
Important: In order to activate the FastFactory your configuration.properties should contain an entry saying 'use.precreation=true'. This is the default in case you started from the template project.