ORIGINAL JSP (WorkItem.jsp)
<c:forEach var="actionItem" items="${workItem.work_action_list}"> <c:if test="${actionItem.workActionClass.work_action_type_id == '1'}" > <%@ include file="inc_done_button.jsp" %> </c:if> <c:if test="${actionItem.workActionClass.work_action_type_id == '2'}" > <c:set var="actionItem" value="${actionItem}" scope="request" /> <c:set var="checklist" value="${actionItem.meat}" scope="request" /> <jsp:include page="inc_dynamic_checklist_v.jsp" flush="true" /> </c:if> etc... </c:forEach> ORIGINAL Java
for (ListIterator<WorkflowInstanceWorkItemAction> actionIter = wfiwi.getWork_action_list().listIterator(); actionIter.hasNext();) { if ("2".equals(work_action_type_id)) { ChecklistInstanceForm ciForm = new ChecklistInstanceForm(this, authenticatedUser); ChecklistInstance ci = null; ci = (ChecklistInstance) ciForm.getChkLstInstanceByWfiWiaOwner(wfiWorkItemAction, authenticatedUser); // Get the meat details for this action and inject it into the object wfiWorkItemAction.setMeat(ci); } } request.setAttribute("workItem", wfiwi); request.setAttribute("workFlowInstance", wfi); NEW JSF (WorkItem.xhtml)
<f:metadata> <o:viewParam name="wfi_wid" value="#{workItemController.wfiwi}" converter="#{workItemConverter}" <f:event type="preRenderView" listener="#{workItemController.preRender}" /> </f:metadata> <ui:repeat var="actionItem" value="#{workItemController.wfiwi.work_action_list}"> <ui:fragment rendered="#{actionItem.workActionClass.workActionType.action_type_id == '1'}"> <stk:done_button actionItem="#{actionItem}" /> <!-- Here I chose custom c --> </ui:fragment> <ui:fragment rendered="#{actionItem.workActionClass.workActionType.action_type_id == '2'}"> <ui:include src="inc_dynamic_checklist.xhtml"> <ui:param name="checklist" value="#{actionItem.meat}" /> </ui:include> </ui:fragment> The makings of my new backing bean
public class WorkItemController implements Serializable { private static final long serialVersionUID = 1L; private WorkflowInstanceWorkItem wfiwi; public void preRender() { if (wfiwi.getWork_action_list() != null) { //loop through and add real model to meat attribute What I am after is a more elegant way to inject the model (what I am calling meat) into my view for each action. Under a work item (single page view), there are multiple actions. Actions that are checklists can be of various types (yes/no/na, quantity major/minor, yes/no/na/resolved, etc).
The composite component done_button was straight forward because I am only accessing the base action model and no meat. For example a snippet of the done_button.xhtml composite component
<ui:fragment rendered="#{cc.attrs.actionItem.is_active != '1'}"> Action is not active for you until the following has been completed: <h:outputText value="#{cc.attrs.actionItem.prerequisite_work_action_list}" escapeXml="false" /> </ui:fragment> but the include of the dynamic_checklist facelet code has me perplexed because my approach of injecting various Objects into this generic attribute meat :) seems wrong. In my original JSP I used <c:set var="checklist" value="${actionItem.meat}" scope="request" /> and then the original JSP for inc_dynamic_checklist_v.jsp looked something like
inc_dynamic_checklist_v.jsp
<form method="post" > <c:out value="${actionItem.workActionClass.name}" /> <c:if test="${checklist.checkListClass.type == '1'}" > <%@ include file="inc_yes_no_na_resolved_checklist.jsp" %> </c:if> <c:if test="${checklist.checkListClass.type == '2'}" > <%@ include file="inc_major_minor_checklist.jsp" %> </c:if> <c:if test="${checklist.checkListClass.type == '3'}" > <%@ include file="inc_quantity_checklist.jsp" %> </c:if> <c:if test="${checklist.checkListClass.type == '4'}" > <%@ include file="inc_yes_no_na_checklist.jsp" %> </c:if> those includes also needed access to the actionItem.meat which was set using c:set in WorkItem.jsp
I'm looking for guidance as to yes I should convert all these includes into composite components, even though I have nested includes. Or I should use basic ui:includes? I know I can send param with either include or cc but do I still use the generic field private Object meat in my model or is there a better way to retrieve these individual action models.
perhaps this but it didn't work
<ui:include src="inc_dynamic_checklist.xhtml" > <ui:param name="wfi_id" value="#{actionItem.workflowInstance.workflow_instance_id}" /> <ui:param name="wfi_aid" value="#{actionItem.wfi_work_item_action_id}" /> </ui:include> and then in the inc_dynamic_checklist.xhtml
<f:metadata> <o:viewParam name="wfi_id" value="#{checklistInstanceView.ci}" converter="#{checklistInstanceConverter}"> <f:attribute name="wfi_id" value="#{param.wfi_id}" /> <f:attribute name="wfi_aid" value="#{param.wfi_aid}" /> </o:viewParam> </f:metadata> UPDATE
Work item backing bean. A work Item contains an array of actions. Actions can be done buttons (action type id=1) checklists (action type id=2), and other things not implemented/shown. What I have now works but is it the right way?
public void preRender() { if (wfiwi.getWork_action_list() != null) { for (ListIterator<WorkflowInstanceWorkItemAction> actionIter = wfiwi.getWork_action_list().listIterator(); actionIter.hasNext();) { WorkflowInstanceWorkItemAction wfiWorkItemAction = new WorkflowInstanceWorkItemAction(); wfiWorkItemAction = actionIter.next(); Long work_action_type_id = wfiWorkItemAction.getWorkActionClass().getWorkActionType().getAction_type_id(); updatePrerequisites(wfiWorkItemAction, wfiwi.getWorkflowInstance(), wfiwi); if (work_action_type_id == 2) { System.out.println("Action Type 2 is Dynamic Checklist Type"); ci = ciRepository.retrieveLatestByWfiWiai(wfiwi.getWorkflowInstance().getWorkflow_instance_id(), wfiWorkItemAction.getWfi_work_item_action_id()); if (ci != null) { if ("1".equals(ci.getCheckListClass().getType())) { List<YesNoNaResolvedAnswer> answer_attribute_list = yesNoNaResolvedDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id()); ci.setAnswer_attribute_list(answer_attribute_list); } if ("2".equals(ci.getCheckListClass().getType())) { List<MajorMinorAnswer> answer_attribute_list = majorMinorAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id()); ci.setAnswer_attribute_list(answer_attribute_list); } if ("3".equals(ci.getCheckListClass().getType())) { List<QuantityAnswer> answer_attribute_list = quantityAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id()); ci.setAnswer_attribute_list(answer_attribute_list); } if ("4".equals(ci.getCheckListClass().getType())) { List<YesNoNaAnswer> answer_attribute_list = yesNoNaAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id()); ci.setAnswer_attribute_list(answer_attribute_list); } wfiWorkItemAction.setMeat(ci); } else { Messages.addFlashErrorMessage("Could not find checklist Instance"); } // wfi_action_list.add(ci); } else { wfiWorkItemAction.setMeat("meat pie"); } } } }
inc_dynamic_checklist.xhtml (see WorkItem.xhtm above for how this is included) This is displaying the "meat"
<ui:fragment rendered="#{checklist.checkListClass.type == '1'}"> <ui:include src="inc_yes_no_na_resolved_checklist.xhtml" /> </ui:fragment> <ui:fragment rendered="#{checklist.checkListClass.type == '2'}"> <ui:include src="inc_major_minor_checklist.xhtml" /> </ui:fragment> <ui:fragment rendered="${checklist.checkListClass.type == '3'}"> <ui:include src="inc_quantity_checklist.xhtml" /> </ui:fragment> <ui:fragment rendered="${checklist.checkListClass.type == '4'}"> <ui:include src="inc_yes_no_na_checklist.xhtml" /> </ui:fragment> model
@Entity public class WorkflowInstanceWorkItemAction implements Serializable { private static final long serialVersionUID = 1L; private String status; private String is_active; @Transient private Object meat; and various mappings