Imports the view tree from another .view file into the current view tree. This control enables you to reuse views as templates.
You can load the view from a resource on the class path and store the view in a shared utility library that can be accessed by multiple CAF applications.
To specify a view on the class path, include a prefix to the import value with classpath:
, for example:
<control component-type='com.webmethods.caf.faces.logic.ImportTemplate' renderer-type=''>
<property name='id' value='import' />
<property name='value' value='classpath:/com/webmethods/caf/test/subpage.view' />
</control>
The phase listener callbacks for the page bean of the imported view execute after the primary page bean phase listener has executed.
Following is a pseudo-code summary of the importTemplateView control behavior:
ImportTemplate { Constructor { 1. Increment a counter to provide a unique instance number for the control instance that is used as a key for the internal_page_bean object. } --------- Internal Utility Methods ------ reloadViewIfChanged() { 1. If the viewId does not match what was previously loaded, reload the imported view. } getInternalPageBean() { if (internal_page_bean instance already exists in pageflow or session scope) { return it. } else { 1. Get the master managed bean that that is associated with the imported template. a) NOTE: This can cause the managed bean to be created and stored in the configured scope. 2. Clone the master managed bean to create the internal_page_bean private copy of it to avoid collision with other imported views using the same name. a) If the clone fails, log an error and try to just make a new instance of the managed bean class. 3. If the master managed bean was configured for pageflow scope, store the cloned object in pageflow scope. Otherwise, store the cloned object in session scope. 4. Return the internal_page_bean. } } propagateParametersToPageBean() { 1. Propagate any non-content param values from the control to the appropriate properties of the specified page bean. } --------- Implementation of PhaseListener interface ------ NOTE: The PhaseListener part is provided for backward compatibility to previous versions. Generally, the IPostPageComponentPhaseListener would take care of the the work instead. beforePhase(ANY_PHASE) { if (rendered property resolves as false) { return and do nothing } else { 1. Push the variables for any ancestor scoped variables into scope. 2. if (phaseId == RENDER_RESPONSE) { call reloadViewIfChanged() } 3. Call getInternalPageBean() 4. Call propagateParametersToPageBean() 5. Pop the variables for any for any ancestor scoped variables from that scope that were pushed in #1 and restore the previous values. } } afterPhase(ANY_PHASE) { do nothing } --------- Implementation of IPostPageComponentPhaseListener interface ------ postPageBeforePhase(ANY_PHASE) { if (rendered property resolves as false) { return and do nothing } else { 1. Push the variables for any ancestor scoped variables into scope. 2. Call reloadViewIfChanged() 3. Call getInternalPageBean() 4. Call propagateParametersToPageBean() 5. If (internal_page_bean implements the PhaseListener interface and configured to listen to the current phaseId) { call internal_page_bean.beforePhase(event) } 6. If (internal_page_bean implements the IPostPageComponentPhaseListener interface and configured to listen to the current phaseId) { call internal_page_bean.postPageBeforePhase(event) } 7. Pop the variables for any for any ancestor scoped variables from that scope that were pushed in #1 and restore the previous values } } postPageAfterPhase(ANY_PHASE) { if (rendered property resolves as false) { return and do nothing } else { 1. Push the variables for any ancestor scoped variables into scope. 2. Call reloadViewIfChanged() 3. Call getInternalPageBean() 4. Call propagateParametersToPageBean() 5. If (internal_page_bean implements the PhaseListener interface and configured to listen to the current phaseId) { call internal_page_bean.afterPhase(event) } 6. If (internal_page_bean implements the IPostPageComponentPhaseListener interface and configured to listen to the current phaseId) { call internal_page_bean.postPageAfterPhase(event) } 7. Pop the variables for any for any ancestor scoped variables from that scope that were pushed in #1 and restore the previous values. } } --------- Override UIComponent methods to make the internal_page_bean variable override the master page bean with the same name while processing the template content ------ encodeBegin { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. } encodeChildren { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Render each of the child controls. 4. Restore the value from #1. } encodeEnd { 1. Restore the value from encodeBegin #1. } processDecodes { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Call super.processDecodes(..) to do the default handling. 4. Restore the value from #1. } processRestoreState { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Ccall super.processRestoreState(..) to do the default handling. 4. Restore the value from #1. } processSaveState { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Call super.processSaveState(..) to do the default handling. 4. Restore the value from #1. } processUpdates { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Call super.processUpdates(..) to do the default handling. 4. Restore the value from #1. } processValidators { 1. Remember what is currently stored in the request attributes with the key == internal_page_bean name. 2. Set the internal_page_bean as a request attribute so it can be resolved with binding expressions. 3. Call super.processValidators(..) to do the default handling. 4. Restore the value from #1. } }
While processing the JSF lifecycle, CAF has global phase listeners that affect this scenario and run in this order:
As demonstrated in the attached example project, if the main page bean named TestDefaultviewView and the page bean of the imported view is named TestimportMeView then:
You would get this sequence during a render request:
TestDefaultviewView: beforePhase[RENDER_RESPONSE 6] TestimportMeView: beforePhase[RENDER_RESPONSE 6] TestimportMeView: postPageBeforePhase[RENDER_RESPONSE 6]
And you would get this sequence during an action request:
TestDefaultviewView: beforePhase[RESTORE_VIEW 1] TestimportMeView: beforePhase[RESTORE_VIEW 1] TestimportMeView: postPageBeforePhase[RESTORE_VIEW 1] TestimportMeView: afterPhase[RESTORE_VIEW 1] TestimportMeView: postPageAfterPhase[RESTORE_VIEW 1] TestDefaultviewView: afterPhase[RESTORE_VIEW 1] TestDefaultviewView: beforePhase[APPLY_REQUEST_VALUES 2] TestimportMeView: beforePhase[APPLY_REQUEST_VALUES 2] TestimportMeView: postPageBeforePhase[APPLY_REQUEST_VALUES 2] TestimportMeView: afterPhase[APPLY_REQUEST_VALUES 2] TestimportMeView: postPageAfterPhase[APPLY_REQUEST_VALUES 2] TestDefaultviewView: afterPhase[APPLY_REQUEST_VALUES 2] TestDefaultviewView: beforePhase[PROCESS_VALIDATIONS 3] TestimportMeView: beforePhase[PROCESS_VALIDATIONS 3] TestimportMeView: postPageBeforePhase[PROCESS_VALIDATIONS 3] TestimportMeView: custom converter.getAsObject("abc") - TestimportMeView: custom validator - value: "abc"; TestimportMeView: afterPhase[PROCESS_VALIDATIONS 3] TestimportMeView: postPageAfterPhase[PROCESS_VALIDATIONS 3] TestDefaultviewView: afterPhase[PROCESS_VALIDATIONS 3] TestDefaultviewView: beforePhase[UPDATE_MODEL_VALUES 4] TestimportMeView: beforePhase[UPDATE_MODEL_VALUES 4] TestimportMeView: postPageBeforePhase[UPDATE_MODEL_VALUES 4] TestimportMeView: afterPhase[UPDATE_MODEL_VALUES 4] TestimportMeView: postPageAfterPhase[UPDATE_MODEL_VALUES 4] TestDefaultviewView: afterPhase[UPDATE_MODEL_VALUES 4] TestDefaultviewView: beforePhase[INVOKE_APPLICATION 5] TestimportMeView: beforePhase[INVOKE_APPLICATION 5] TestimportMeView: postPageBeforePhase[INVOKE_APPLICATION 5] TestimportMeView: actionListener TestimportMeView: doAction TestimportMeView: afterPhase[INVOKE_APPLICATION 5] TestimportMeView: postPageAfterPhase[INVOKE_APPLICATION 5] TestDefaultviewView: afterPhase[INVOKE_APPLICATION 5] TestDefaultviewView: beforePhase[RENDER_RESPONSE 6] TestimportMeView: beforePhase[RENDER_RESPONSE 6] TestimportMeView: postPageBeforePhase[RENDER_RESPONSE 6] TestimportMeView: custom converter.getAsString("abc") -
Info | Value |
---|---|
Component Type | com.webmethods.caf.faces.logic.ImportTemplate |
Handler Class | com.webmethods.caf.faces.component.DynamicControlHandler |
Renderer Type | None |
Description | Imports the view tree from another .view file into the current view tree |
Palette Location | CAF Core/Control/Logic/Import Template View |
Name | Required | Type | Description |
---|---|---|---|
id | false | java.lang.String | Control identifier |
rendered | false | javax.el.ValueExpression
(must evaluate to boolean )
|
True to render control; false to ignore it
If not specified, the default value is "true". |
value | false | javax.el.ValueExpression
(must evaluate to java.lang.Object )
| Control value |
Output generated by Vdldoc View Declaration Language Documentation Generator.