Basic Customization > User Interface Customization > Constructing Wizards > Building Wizards to Create a Single Object > Customization Points
  
Customization Points
Creating Your Form Processor and Form Processor Delegates
This section assumes you are familiar with the standard wizard processing framework described in the Wizard Processing.
The class com.ptc.core.components.forms.CreateObjectFormProcessor is available as a default form processor for wizards creating Persistable objects. This class may be extended as necessary to meet your purposes.
The CreateObjectFormProcessor does the following:
preprocess() method
extracts all of the ObjectBean form data that has a special name attribute as described in Attribute Tables.
creates a TypeInstance for the new object and applies the attribute values from the form to it, validating the values against any constraints defined for the attributes in the Type and Attribute Management utility
converts the TypeInstance into a Persistable and sets it as the “object” attribute on the ObjectBean
calls super.preProcess() to call the preprocess() methods of any FormProcessorDelegates registered for the wizard
doOperation() method
calls super.doOperation() to call the doOperation() methods of any FormProcessorDelegates registered for the wizard
calls PersistenceHelper.manager.store() to store the Persistable in the database
getSuccessFeedbackMessage() method (called by setResultNextAction())
This method is called when FormResult is SUCCESS.This constructs the FeedbackMessage see Inline Messaging for more information on configuring message content.
In the UI this inline message is shown as below for single object creation:
For Multi-object create the UI as shown below:
Note the CreateObjectFormProcessor does not implement postProcess() or postTransactionProcess() methods so these are inherited from the DefaultObjectFormProcessor. See the javadoc for more information.
If you are extending an existing Windchill business class, there may be a processor specific to that class that you should use or extend instead of CreateObjectFormProcessor. These are shown in the table below. Consult the javadoc for these classes for more information on their behavior.
If your class extends:
Use processor class:
WTPart
If creating a wizard to be launched from a workspace:
com.ptc.windchill.enterprise.part.forms.CreatePartFromW orkspaceFormProcessor
If creating a wizard to be launched from the Edit Structure client:
com.ptc.windchill.enterprise.part.forms.CreatePartFromTa bularInputProcessor
All other single-object creation wizards:
com.ptc.windchill.enterprise.part.forms.CreatePartFormPro cessor
WTDocument
For creating a document from a template:
com.ptc.windchill.enterprise.doc.forms.CreateDocFromTe mplateFormProcessor
For creating a document template:
com.ptc.windchill.enterprise.doc.forms.CreateDocTemplat eFormProcessor
For all other single-object create wizards:
com.ptc.core.windchill.enterprise.doc.forms.CreateDocFor mProcessor
WTChangeIssues
com.ptc.windchill.enterprise.change2.forms.processors.Cre ateProblemReportFormProcessor
WTChangeRequest2
com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeRequestFormProcessor
WTChangeOrder2
com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeNoticeFormProcessor
WTChangeActivity2
com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeTaskFormProcessor
WTVariance
com.ptc.windchill.enterprise.change2.forms.processors.Cre ateVarianceFormProcessor.
If the behavior of one of the provided form processors meets your needs, you do not need to write your own processor, just specify that processor as the value of the class attribute of the command subtag of your wizard action. If it does not meet your needs, you should write a subclass of it to process the wizard form data. Note that you do not need to create your own processor if you only want to provide special code for setting an attribute. In that case, you need only to write a FormProcessorDelegate to handle this task. Remember to register the FormProcessorDelegate in a hidden form field and make sure that the attribute input field does NOT have a special name attribute that will be recognized by the CreateObjectFormProcessor. See Attribute Tables for more information.
Note that you do not need to create your own processor if you only want to provide special code for setting an attribute. In that case, you need only to write a FormProcessorDelegate to handle this task. Remember to register the FormProcessorDelegate in a hidden form field and make sure that the attribute input field does NOT have a special name attribute that will be recognized by the CreateObjectFormProcessor.
The FormProcessorDelegate should extend from DefaultObjectFormProcessorDelegate. NumberPropertyProcessor and KeepCheckedOutDelegate are examples of custom FormProcessorDelegates available out of the box. The class structure for FormProcessorDelegates is shown below.
If you create your own processor, be aware that its preProcess() method will be called by the standard validator classes after each wizard step. Make sure you do not modify the database in this method.
Here are some of the more common cases where you may need to write your own ObjectFormProcessor class and the methods you would override to handle them:
Case 1: You need to perform a different action when the wizard closes.
For example, perhaps you want to load a new page when the wizard closes instead of refreshing the launch page. Or, perhaps your wizard can be launched from multiple points and you want refresh the launch page in one case and load a new page in another case.
Solution: Subclass the out-of-the-box processor and override the setResultNextAction method. From the NmCommand.getCompContext() method you can obtain information about the launch context of the wizard. Here is an example of how this is done for the create baseline client:
String compContext = cb.getCompContext();
if (compContext != null) {
try {
NmContext compContextObj = NmContext.fromString(compContext);
Stack<NmContextItem> contextItems = compContextObj.getContextItems();
for (NmContextItem contextItem : contextItems) {
String action = contextItem.getAction();
if ("addToBaseline".equals(action) ||
"addToBaselineSingle".equals(action) ||
"addToBaselineStep".equals(action)) {

< set some next action >
}
}
.
.
.
Note that if your wizard is launched from a table and you have specified “ajax=”row”” on the wizard action, you must set the refreshInfo attribute on the FormResult to tell the system what rows to refresh. Typically, the attributes of the DynamicRefreshInfo object will be as follows:
action = NmCommandBean.DYNAMIC_ADD
oid = the NmOid of the object that was created
location = the NmOid of the table object containing the new row. Typically, this will be a folder.
If you have used an ajax attribute of “page” or “component” you do not need to set the refreshInfo attribute.
See the Customizing the UI with Ajax section in the Customizing HTML Clients Using the Windchill JSP Framework chapter and the javadoc for the FormResult and FormProcessingStatus classes for more information.
Case 2: You need to do some post processing after the object is persisted.
For example, change object wizards have a dialog to allow the user to submit the object to workflow immediately after creation. For this, they need to perform another operation after the object is created. In some cases, this kind of requirement can be handled by creating an ObjectFormProcessorDelegate for the input field and implementing a postProcess() or postTransactionProcess() method on it that will be called automatically by the infrastructure. However, in other cases you may prefer for your form processor to handle this. For example, you cannot control the order in which FormProcessorDelegates are called so if operation ordering is a requirement you would need to do the operations in the form processor.
Solution: Subclass the CreateObjectFormProcessor and override the postProcess() or postTransactionProcess() method (which are inherited from DefaultObjectFormProcessor) to perform your operation.
(Note that if you put a “Keep checked out checkbox” in your wizard by including the keepCheckedOutCheckbox.jspf file, this will be processed automatically by the KeepCheckedOutDelegate. You do not need to handle this).
Case 3: You need to use a special API to persist the object.
For example, change objects are persisted using the StandardChangeService2 class, which handles some life cycle and foldering tasks in addition to persisting the object.
Solution: Subclass the out-of-the-box processor and override the doOperation() method. In your method you can’t call the super method, but you should still make sure the doOperation() method of any registered FormProcessorDelegates are called. You can accomplish that by calling the processDelegates() method inherited from DefaultObjectFormProcessor. For example:
FormResult doOperationResult = new FormResult();
doOperationResult.setStatus(FormProcessingStatus.SUCCESS);
doOperationResult = processDelegates (DO_OPERATION, clientData,
objectBeanList);
if (!continueProcessing(doOperationResult)) {
return doOperationResult;
}

try
{
< persist the object >
}
catch(WTException e)
{
< do error handling >
}
return doOperationResult;
Note that delegates are called after form processor tasks in most processing phases, but in the doOperation phase they should be called before the form processor does its tasks. This is to allow delegates to perform operations after all attributes have been set but before the object is persisted.
Case 4: You need to set attributes on the new object programmatically
You may have attributes that you need to set on the object before it is persisted which are not exposed in the UI.
Solution: There are alternate ways to handle this.
Create a FormProcessorDelegate and implement its preProcess() method. In that method, set the attribute values on the object in the ObjectBean. Add a hidden form field to your wizard jsp specifying the name of your delegate, which will be automatically instantiated by the framework. For example:
<input type="hidden" name="
${createBean.formProcessorDelegateConstant}" value=" <path name
of your delegate
> ">
Subclass the out-of-the-box processor and override the preProcess() method. You can call the createItemInstance() method of the superclass to create the Persistable for you and then set the attributes you desire on the Persistable. For example:
FormResult preProcessResult = new
FormResult(FormProcessingStatus.SUCCESS);
for (ObjectBean objBean: objectBeans) {
FormResult objectResult =
new FormResult(FormProcessingStatus.SUCCESS);
objBean.setObject(createItemInstance(clientData,
objBean, objectResult));
preProcessResult =
mergeIntermediateResult(phaseResult, objectResult);
if (!continueProcessing(preProcessResult)) {
return preProcessResult;
}
Object newObj = objBean.getObject();

< set additional attributes on the new object here>
}

// Call processDelegates() which will call registered
processor delegates
delegatesResult = processDelegates(DO_OPERATION,
clientData, objectBeanList);
preProcessResult =
mergeIntermediateResult(preProcessResult, delegatesResult);

if (!continueProcessing(preProcessResult)) {
return preProcessResult;
}
Note that the above example is written so that the processor could be used for wizards creating more than one object.
In general, it is probably preferable to use the delegate approach for setting your attributes rather than the subclass approach as it will insulate you from any modifications that might be made to the CreateObjectFormProcessor preprocess() method in the future.