Liferay already implemented workflow management for some
of assets like Web content, Blogs, wikis, document library and Message Boards.
These assets we can enable Kaleo workflow so that all submission of each assets
going through the workflow management.
Liferay also have given support to implement workflow
management to custom assets or we can say custom portlets and this is one of exciting
thing in real time development. Liferay already have given workflow API to
implement workflow to our custom assets/custom portlets.
Go through following Post for better understanding
about workflow in Liferay portal.
Before implement Kaleo workflow to custom assets we
need to check Liferay portal have workflow engine in the portal.
As we know that from Liferay 6.2 onwards Kaleo-web
bundled with Liferay portal server so we don’t need to install again.
If older version then we need to download appropriate
version form Liferay Market Place and deploy into Liferay portal. 
Based on Liferay portal licence it can be available as
CE and EE
Prerequisite:
Liferay Portal Should have workflow Engine and Kaleo
default implementation for Liferay portal and out of box you can integrate with
other workflow management and that should follow the JBPM (jBoss Business Process
Management) Notation.
Download Kaleo-web from market place and it will be
available as .lpkg and you can place
it in Liferay deploy directory so that it will be deployed and this
step only for older version not for Liferay 6.2.
You can also install it from Liferay Control panel
there you can find market place application from there you can install it.
Now we are ready with Kaleo workflow engine for our
Liferay portal so that we can enable this workflow for default assets and
custom assets then each submission going through the workflow process.
Example
Scenario for Kaleo Implementation for Custom Assets.
Assume we have Feedback form once we submit the
feedback that should travel through workflow management and while in the
process other authorized users review the feedback based on that it will be
approved or rejected and this is our scenario for implementation.
Required
Steps;
Create
Portlet and Design Feedback form
Create
service builder for portlet and define entity for store feedback data.
Implement
Workflow for Feedback From/Feedback Custom Asset.
Create
Portlet and Design Feedback form
Create Liferay MVC Portlet and Design feedback form
with required fields and create Liferay MVC Portlet is very straight forward
way.
Create
service builder for portlet and define entity for store feedback data
Now create Service Builder for Feedback portlet and
define entity in service.xml with required columns.
The
following is entity in service.xml
| 
<entity name="Feedback"
  uuid="true" local-service="true" 
remote-service="false"> 
<column name="feedbackId"
  type="long" primary="true"
  /> 
<column name="feedbackDate"
  type="Date" /> 
<column name="feedbackText"
  type="String" /> 
<column name="feedbackSubject"
  type="String" /> 
<column name="feedBackStatus"
  type="int" /> 
<column name="statusByUserId"
  type="long" /> 
<column name="statusDate"
  type="Date" /> 
<column name="companyId"
  type="long" /> 
<column name="groupId"
  type="long" /> 
<column name="userId"
  type="long" /> 
<order> 
<order-column name="feedbackId"
  order-by="asc" /> 
<order-column name="feedbackDate"
  order-by="desc" /> 
</order> 
<finder name="GroupId"
  return-type="Collection"> 
<finder-column name="groupId"
  /> 
</finder> 
<finder name="CompanyId"
  return-type="Collection"> 
<finder-column name="companyId"
  /> 
</finder> 
<finder name="feedbackText"
  return-type="Collection"> 
<finder-column name="feedbackText"
  /> 
</finder> 
<finder name="G_S"
  return-type="Collection"> 
<finder-column name="groupId"
  /> 
<finder-column name="feedBackStatus"
  /> 
</finder> 
<reference package-path="com.liferay.portal"
  entity="User" /> 
<reference package-path="com.liferay.portlet.asset"
  entity="AssetEntry" /> 
<reference package-path="com.liferay.portal"
  entity="WorkflowDefinitionLink"></reference> 
<reference package-path="com.liferay.portal"
  entity="WorkflowInstanceLink"></reference> 
</entity> | 
Once you define entity run service build so that it
will be crated required classes and interfaces. we will use these java classes’
methods to interact with database.
Implement
Workflow for Feedback From/Feedback Custom Asset.
We are implementing workflow to custom asset and here
Feedback is our custom asset. Liferay workflow management will use these assets
to in the workflow management.
Asset Type:
Feedback.
Note:
All workflow task will be identified by custom asset
that is Feedback
Steps
to Impalement Workflow for Custom Asset.
Implement
Custom Workflow Handler to Custom Asset/Portlet
Register
Custom Workflow handler with Portlet
Implement
Asset Renderer Java Class
Implement
Asset Renderer Factory Java Class
Register
Asset Renderer Factory with Portlet.
Enable
Workflow to Custom Asset
Start
Workflow Instance to Each Asset Submission
Implement
Custom Workflow Handler to Custom Asset/Portlet
When we implement workflow for custom asset/portlet
first we need to implement workflow handler and in the
implementation we will override some of methods based our requirement.
Custom workflow handle must extends BaseWorkflowHandler
or it should implement WorkflowHandler interface.
When we enable workflow for custom asset then custom
handle will be invoked and it will call the implemented methods.
The
following is Syntax of Custom Workflow Handler.
| 
public
  class FeedbackWorkflowHandler extends BaseWorkflowHandler{ 
} | 
Register
Custom Workflow handler with Portlet
Now we need to register custom workflow handle with
portlet and we will use Liferay-portlet.xml file. <workflow-handler/>
is tag to register the workflow handle and all workflow mechanism for this
portlet will be taken care by  registered
custom handler.
Implement
Asset Renderer Java Class
Asset Renderer class will provide full information of
custom asset. And this we will use specially to show full details of asset
information when task in the workflow process. 
We need to extends BaseAssetRenderer and
need to override some of methods 
The
following is Asset Renderer Syntax Implementation Class
| 
public
  class FeedbackAssetRenderer extends BaseAssetRenderer{ 
} | 
Implement
Asset Renderer Factory Java Class
Asset
Renderer Factory class will provide asset object to Asset
renderer class. And here we will get required asset object and pass to Asser
Render.
The
following is Syntax Implementation of AssetRendererFactory 
| 
public class FeedbackAssetRendererFactory
  extends BaseAssetRendererFactory { 
} | 
Register Asset Renderer
Factory with Portlet.
Now we need to register Asset Renderer Factory class
with portlet in the Liferay-portlet.xml using <asset-renderer-factory/>.
Asset Renderer factory provide required object for Asset and to show full
details of asset then we will use asset object to showcase data.
Enable
Workflow to Custom Asset
Enable Workflow to custom asset will be taken care by
workflow handler and based on our custom handler our asset comes as part
default configuration in the workflow there we will enable workflow to custom
asset 
Generally the following method we will use to enable
workflow to Asset 
Class: WorkflowDefinitionLinkLocalServiceUtil
| 
public
  static void updateWorkflowDefinitionLink(long userId, 
long
  companyId, long groupId, java.lang.String className, long classPK, 
long
  typePK, java.lang.String workflowDefinition) | 
Note:
Our Asset will be comes under default workflow configuration
list so we won’t write this code anywhere in the implementation.
Start
Workflow Instance to Each Asset Submission
Now we will start workflow instance to each form submission
so that asset will be going through workflow engine.
The
following is method in WorkflowHandlerRegistryUtil
| 
Method
  Signature 
public
  static void startWorkflowInstance( 
final
  long companyId, final long groupId, final long userId, 
String
  className, final long classPK, final Object model, 
ServiceContext
  serviceContext, 
Map<String,
  Serializable> workflowContext) 
Example Usage: 
WorkflowHandlerRegistryUtil.startWorkflowInstance( 
feedback.getCompanyId(),
  feedback.getGroupId(), themeDisplay.getUserId(), 
Feedback.class.getName(),
  feedback.getPrimaryKey(), feedback, 
serviceContext); | 
Before start workflow instance we need to insert entry
in Asset
Entry table so that when we fetch the workflow records it will be
searched in asset entries table.
The
following is insert Asset Entry
| 
AssetEntryLocalServiceUtil.updateEntry(userId,
  feedback.getGroupId(), 
Feedback.class.getName(),
  feedback.getFeedbackId(), 
serviceContext.getAssetCategoryIds(), 
serviceContext.getAssetTagNames()); | 
Download
Portlet
Compete
Code Implementation
Portlet Name: FeedBakcWorkFlow-portlet
Portlet.xml
file
| 
<?xml version="1.0"?> 
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
  http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"> 
<portlet> 
<portlet-name>FeedBakcWorkFlow</portlet-name> 
<display-name>FeedBakcWorkFlow</display-name> 
<portlet-class> 
com.meera.workflow.customasset.FeedBakcWorkFlowAction 
</portlet-class> 
<init-param> 
<name>view-template</name> 
<value>/html/workflow/view.jsp</value> 
</init-param> 
<expiration-cache>0</expiration-cache> 
<supports> 
<mime-type>text/html</mime-type> 
<portlet-mode>view</portlet-mode> 
</supports> 
<portlet-info> 
<title>FeedBakcWorkFlow</title> 
<short-title>FeedBakcWorkFlow</short-title> 
<keywords></keywords> 
</portlet-info> 
<security-role-ref> 
<role-name>administrator</role-name> 
</security-role-ref> 
<security-role-ref> 
<role-name>guest</role-name> 
</security-role-ref> 
<security-role-ref> 
<role-name>power-user</role-name> 
</security-role-ref> 
<security-role-ref> 
<role-name>user</role-name> 
</security-role-ref> 
</portlet> 
</portlet-app> | 
Liferay-portlet.xml
file
| 
<?xml version="1.0"?> 
<!DOCTYPE liferay-portlet-app
  PUBLIC "-//Liferay//DTD
  Portlet Application 6.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_2_0.dtd"> 
<liferay-portlet-app> 
<portlet> 
<portlet-name>FeedBakcWorkFlow</portlet-name> 
<icon>/icon.png</icon> 
<asset-renderer-factory>com.meera.workflow.customasset.FeedbackAssetRendererFactory</asset-renderer-factory> 
<workflow-handler>com.meera.workflow.customasset.FeedbackWorkflowHandler</workflow-handler> 
<header-portlet-css>/css/main.css</header-portlet-css> 
<footer-portlet-javascript> 
/js/main.js 
</footer-portlet-javascript> 
<css-class-wrapper>feedbakcworkflow-portlet</css-class-wrapper> 
</portlet> 
<role-mapper> 
<role-name>administrator</role-name> 
<role-link>Administrator</role-link> 
</role-mapper> 
<role-mapper> 
<role-name>guest</role-name> 
<role-link>Guest</role-link> 
</role-mapper> 
<role-mapper> 
<role-name>power-user</role-name> 
<role-link>Power User</role-link> 
</role-mapper> 
<role-mapper> 
<role-name>user</role-name> 
<role-link>User</role-link> 
</role-mapper> 
</liferay-portlet-app> | 
Liferay-display.xml
file
| 
<?xml version="1.0"?> 
<!DOCTYPE display
  PUBLIC "-//Liferay//DTD
  Display 6.2.0//EN" "http://www.liferay.com/dtd/liferay-display_6_2_0.dtd"> 
<display> 
<category name="category.sample"> 
</category> 
<category name="category.workflow"> 
<portlet id="FeedBakcWorkFlow"></portlet> 
</category> 
</display> | 
service.xml
file
| 
<?xml version="1.0"
  encoding="UTF-8"?> 
<!DOCTYPE service-builder
  PUBLIC "-//Liferay//DTD
  Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd"> 
<service-builder package-path="com.meera.workflow.db"> 
<author>LiferaySavvy</author> 
<namespace>LS</namespace> 
<entity name="Feedback"
  uuid="true" local-service="true" 
remote-service="false"> 
<column name="feedbackId"
  type="long" primary="true"
  /> 
<column name="feedbackDate"
  type="Date" /> 
<column name="feedbackText"
  type="String" /> 
<column name="feedbackSubject"
  type="String" /> 
<column name="feedBackStatus"
  type="int" /> 
<column name="statusByUserId"
  type="long" /> 
<column name="statusDate"
  type="Date" /> 
<column name="companyId"
  type="long" /> 
<column name="groupId"
  type="long" /> 
<column name="userId"
  type="long" /> 
<order> 
<order-column name="feedbackId"
  order-by="asc" /> 
<order-column name="feedbackDate"
  order-by="desc" /> 
</order> 
<finder name="GroupId"
  return-type="Collection"> 
<finder-column name="groupId"
  /> 
</finder> 
<finder name="CompanyId"
  return-type="Collection"> 
<finder-column name="companyId"
  /> 
</finder> 
<finder name="feedbackText"
  return-type="Collection"> 
<finder-column name="feedbackText"
  /> 
</finder> 
<finder name="G_S"
  return-type="Collection"> 
<finder-column name="groupId"
  /> 
<finder-column name="feedBackStatus"
  /> 
</finder> 
<reference package-path="com.liferay.portal"
  entity="User" /> 
<reference package-path="com.liferay.portlet.asset"
  entity="AssetEntry" /> 
<reference package-path="com.liferay.portal"
  entity="WorkflowDefinitionLink"></reference> 
<reference package-path="com.liferay.portal"
  entity="WorkflowInstanceLink"></reference> 
</entity> 
</service-builder> | 
liferay-plugin-package.properties
| 
name=FeedBakcWorkFlow 
module-group-id=liferay 
module-incremental-version=1 
tags= 
short-description= 
long-description= 
change-log= 
page-url=http://www.liferay.com 
author=Liferay, Inc. 
licenses=LGPL 
liferay-versions=6.2.0+ 
portal-dependency-jars=\ 
jstl-api.jar,\ 
jstl-impl.jar 
portal-dependency-tlds=\ 
c.tld | 
FeedBakcWorkFlowAction.java
| 
package
  com.meera.workflow.customasset; 
import
  java.io.IOException; 
import
  java.util.Date; 
import
  javax.mail.internet.AddressException; 
import
  javax.portlet.ActionRequest; 
import
  javax.portlet.ActionResponse; 
import
  com.liferay.counter.service.CounterLocalServiceUtil; 
import
  com.liferay.portal.NoSuchWorkflowDefinitionLinkException; 
import
  com.liferay.portal.PortalException; 
import
  com.liferay.portal.SystemException; 
import
  com.liferay.portal.kernel.servlet.SessionErrors; 
import
  com.liferay.portal.kernel.servlet.SessionMessages; 
import
  com.liferay.portal.kernel.util.ParamUtil; 
import
  com.liferay.portal.kernel.util.WebKeys; 
import
  com.liferay.portal.kernel.workflow.WorkflowConstants; 
import
  com.liferay.portal.kernel.workflow.WorkflowDefinitionManagerUtil; 
import
  com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil; 
import
  com.liferay.portal.model.WorkflowDefinitionLink; 
import
  com.liferay.portal.service.ServiceContext; 
import
  com.liferay.portal.service.ServiceContextFactory; 
import
  com.liferay.portal.service.WorkflowDefinitionLinkLocalServiceUtil; 
import
  com.liferay.portal.theme.ThemeDisplay; 
import
  com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil; 
import
  com.liferay.util.bridges.mvc.MVCPortlet; 
import
  com.meera.workflow.db.model.Feedback; 
import
  com.meera.workflow.db.service.FeedbackLocalServiceUtil; 
/** 
*
  Portlet implementation class FeedBakcWorkFlowAction 
*/ 
public
  class FeedBakcWorkFlowAction extends MVCPortlet { 
public
  void submitFeedback(ActionRequest actionRequest, 
ActionResponse
  actionResponse) throws IOException, 
AddressException,com.liferay.portal.kernel.exception.PortalException,
  com.liferay.portal.kernel.exception.SystemException { 
ThemeDisplay
  themeDisplay =
  (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY); 
String
  feedBackMessage = ParamUtil.getString(actionRequest,
  "feedbackMessage"); 
String
  feedbackSubject = ParamUtil.getString(actionRequest,
  "feedbackSubject"); 
ServiceContext
  serviceContext = ServiceContextFactory.getInstance(Feedback.class.getName(),
  actionRequest); 
try
  { 
Feedback
  feedback=FeedbackLocalServiceUtil.createFeedback(CounterLocalServiceUtil.increment()); 
feedback.setCompanyId(themeDisplay.getCompanyId()); 
feedback.setGroupId(themeDisplay.getScopeGroupId()); 
feedback.setFeedbackDate(new
  Date()); 
feedback.setFeedbackText(feedBackMessage); 
feedback.setFeedbackSubject(feedbackSubject); 
feedback.setFeedBackStatus(WorkflowConstants.STATUS_DRAFT); 
feedback.setUserId(themeDisplay.getUserId()); 
feedback.setStatusByUserId(themeDisplay.getUserId()); 
feedback=FeedbackLocalServiceUtil.addFeedback(feedback); 
WorkflowDefinitionLink
  workflowDefinitionLink=null; 
try{ 
workflowDefinitionLink= 
WorkflowDefinitionLinkLocalServiceUtil. 
getDefaultWorkflowDefinitionLink(themeDisplay.getCompanyId(),
  Feedback.class.getName(), 0, 0); 
}catch
  (Exception e) { 
if(e
  instanceof NoSuchWorkflowDefinitionLinkException){ 
SessionMessages.add(actionRequest.getPortletSession(),"workflow-not-enabled"); 
} 
e.printStackTrace(); 
} 
//checking
  workflow defintion is enabled to feedback asset or not 
if(feedback!=null&&workflowDefinitionLink!=null){ 
//add
  feedback asset in asset entry table 
AssetEntryLocalServiceUtil.updateEntry(themeDisplay.getUserId(),
  feedback.getGroupId(), 
Feedback.class.getName(),
  feedback.getFeedbackId(), 
serviceContext.getAssetCategoryIds(), 
serviceContext.getAssetTagNames()); 
//start
  workflow instance to feedback. 
WorkflowHandlerRegistryUtil.startWorkflowInstance( 
feedback.getCompanyId(),
  feedback.getGroupId(), themeDisplay.getUserId(), 
Feedback.class.getName(),
  feedback.getPrimaryKey(), feedback, 
serviceContext); 
} 
if(feedback==null){ 
SessionErrors.add(actionRequest.getPortletSession(),"feedback-submit-failed"); 
}else{ 
SessionMessages.add(actionRequest.getPortletSession(),"feedback-submit-success"); 
} 
}
  catch (Exception e) { 
if(e
  instanceof NoSuchWorkflowDefinitionLinkException){ 
SessionMessages.add(actionRequest.getPortletSession(),"workflow-not-enabled"); 
} 
e.printStackTrace(); 
} 
actionResponse.setRenderParameter("mvcPath",
  "/html/workflow/feedback.jsp"); 
} 
} | 
FeedbackWorkflowHandler.java
| 
package
  com.meera.workflow.customasset; 
import
  java.io.Serializable; 
import
  java.util.Date; 
import
  java.util.Locale; 
import
  java.util.Map; 
import
  com.liferay.portal.kernel.exception.PortalException; 
import
  com.liferay.portal.kernel.exception.SystemException; 
import
  com.liferay.portal.kernel.util.GetterUtil; 
import
  com.liferay.portal.kernel.workflow.BaseWorkflowHandler; 
import
  com.liferay.portal.kernel.workflow.WorkflowConstants; 
import
  com.liferay.portal.service.ServiceContext; 
import
  com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil; 
import
  com.meera.workflow.db.model.Feedback; 
import
  com.meera.workflow.db.service.FeedbackLocalServiceUtil; 
/** 
*
  Portlet implementation class FeedbackAction 
*/ 
public
  class FeedbackWorkflowHandler extends BaseWorkflowHandler{ 
public
  String getClassName() { 
return
  CLASS_NAME; 
} 
public
  String getType(Locale locale) { 
return
  "Feedback"; 
} 
public  Feedback updateStatus(int status, 
Map<String,
  Serializable> workflowContext) throws PortalException, 
SystemException
  { 
long
  userId =
  GetterUtil.getLong(workflowContext.get(WorkflowConstants.CONTEXT_USER_ID)); 
long
  resourcePrimKey =
  GetterUtil.getLong(workflowContext.get(WorkflowConstants.CONTEXT_ENTRY_CLASS_PK)); 
Feedback
  feedback = FeedbackLocalServiceUtil.getFeedback(resourcePrimKey); 
feedback.setFeedBackStatus(status); 
feedback.setStatusByUserId(userId); 
feedback.setStatusDate(new
  Date()); 
feedback=FeedbackLocalServiceUtil.updateFeedback(feedback); 
if
  (status == WorkflowConstants.STATUS_APPROVED) { 
AssetEntryLocalServiceUtil.updateVisible(Feedback.class.getName(), 
resourcePrimKey,
  true); 
}
  else { 
AssetEntryLocalServiceUtil.updateVisible(Feedback.class.getName(), 
resourcePrimKey,
  false); 
} 
return
  feedback; 
} 
public
  static final String CLASS_NAME = Feedback.class.getName(); 
} | 
FeedbackAssetRendererFactory.java
| 
package
  com.meera.workflow.customasset; 
import
  com.liferay.portal.kernel.exception.PortalException; 
import
  com.liferay.portal.kernel.exception.SystemException; 
import
  com.liferay.portlet.asset.model.AssetRenderer; 
import
  com.liferay.portlet.asset.model.BaseAssetRendererFactory; 
import
  com.meera.workflow.db.model.Feedback; 
import
  com.meera.workflow.db.service.FeedbackLocalServiceUtil; 
/** 
*
  Portlet implementation class FeedbackAction 
*/ 
public
  class FeedbackAssetRendererFactory extends BaseAssetRendererFactory { 
@Override 
public
  AssetRenderer getAssetRenderer(long classPK, int type) 
throws
  PortalException, SystemException { 
Feedback
  feedback = FeedbackLocalServiceUtil.getFeedback(classPK); 
return
  new FeedbackAssetRenderer(feedback); 
} 
@Override 
public
  String getClassName() { 
return
  CLASS_NAME; 
} 
@Override 
public
  String getType() { 
return
  TYPE; 
} 
public
  static final String TYPE = "Feedback"; 
public
  static final String CLASS_NAME = Feedback.class.getName(); 
} | 
FeedbackAssetRenderer.java
| 
package
  com.meera.workflow.customasset; 
import
  java.util.Locale; 
import
  javax.portlet.RenderRequest; 
import
  javax.portlet.RenderResponse; 
import
  com.liferay.portal.kernel.exception.PortalException; 
import
  com.liferay.portal.kernel.exception.SystemException; 
import
  com.liferay.portal.service.UserLocalServiceUtil; 
import
  com.liferay.portlet.asset.model.BaseAssetRenderer; 
import
  com.meera.workflow.db.model.Feedback; 
/** 
*
  Portlet implementation class FeedbackAction 
*/ 
public
  class FeedbackAssetRenderer extends BaseAssetRenderer{ 
private
  Feedback _feedback; 
public
  FeedbackAssetRenderer(Feedback feedback) { 
_feedback
  = feedback; 
} 
public
  long getClassPK() { 
return
  _feedback.getFeedbackId(); 
} 
public
  long getGroupId() { 
return
  _feedback.getGroupId(); 
} 
public
  String getSummary(Locale arg0) { 
return
  _feedback.getFeedbackText(); 
} 
public
  String getTitle(Locale arg0) { 
return
  _feedback.getFeedbackSubject(); 
} 
public
  long getUserId() { 
return
  _feedback.getUserId(); 
} 
public
  String getUuid() { 
return
  _feedback.getUuid(); 
} 
public
  String render(RenderRequest request, RenderResponse response, String
  template) 
throws
  Exception 
{ 
if
  (template.equals(TEMPLATE_FULL_CONTENT)) { 
request.setAttribute("feedBackObject",_feedback); 
return
  "/html/workflow/view_feedbck.jsp"; 
} 
else 
{ 
return
  null; 
} 
} 
@Override 
public
  String getUserName() { 
//
  TODO Auto-generated method stub 
String
  userName=null; 
try
  { 
userName=
  UserLocalServiceUtil.getUser(_feedback.getUserId()).getFullName(); 
}
  catch (PortalException e) { 
//
  TODO Auto-generated catch block 
e.printStackTrace(); 
}
  catch (SystemException e) { 
//
  TODO Auto-generated catch block 
e.printStackTrace(); 
return
  userName; 
} 
return
  userName; 
} 
@Override 
public
  String getClassName() { 
//
  TODO Auto-generated method stub 
return
  Feedback.class.getName(); 
} 
} | 
Init.jsp
| 
<%@ taglib
  uri="http://liferay.com/tld/aui" prefix="aui" %> 
<%@ taglib
  uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %> 
<%@ taglib
  uri="http://liferay.com/tld/security" prefix="liferay-security" %> 
<%@ taglib
  uri="http://liferay.com/tld/theme" prefix="liferay-theme" %> 
<%@ taglib
  uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> 
<%@ taglib
  uri="http://liferay.com/tld/util" prefix="liferay-util" %> 
<%@ taglib
  uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> 
<%@ taglib
  uri="http://java.sun.com/jsp/jstl/core"
  prefix="c" %> 
<%@ page
  import="javax.portlet.PortletPreferences"
  %> 
<%@ page
  import="com.liferay.portal.kernel.util.Validator"
  %> 
<%@ page
  import="com.liferay.portal.kernel.util.ParamUtil"
  %> 
<%@ page
  import="com.liferay.portlet.PortletPreferencesFactoryUtil"
  %> 
<%@ page
  import="com.liferay.portal.util.PortalUtil"
  %> 
<%@ page
  import="com.liferay.portal.kernel.dao.search.ResultRow"
  %> 
<%@ page
  import="com.liferay.portal.kernel.util.ParamUtil"
  %> 
<%@ page
  import="com.liferay.portal.kernel.util.WebKeys"
  %> 
<%@ page
  import="com.liferay.portal.model.User" %> 
<%@ page
  import="com.liferay.portal.service.UserLocalServiceUtil"
  %> 
<%@ page
  import="javax.portlet.PortletURL" %> 
<%@page import="javax.portlet.WindowState"
  %> 
<%@page import="java.text.Format"%> 
<%@page import="com.liferay.portal.kernel.util.FastDateFormatFactoryUtil"%> 
<%@page import="com.liferay.portal.kernel.util.GetterUtil"%> 
<%@page import="com.liferay.portal.kernel.util.StringPool"%> 
<%@page import="java.util.*"%> 
<%@page import="com.liferay.portal.kernel.util.OrderByComparator"%> 
<portlet:defineObjects /> 
<liferay-theme:defineObjects /> | 
View.jsp
| 
<%@ include
  file="init.jsp"%> 
<% 
String tabs1 =
  ParamUtil.getString(request, "tabs1", "Aproved Feedback"); 
PortletURL
  portletURL = renderResponse.createRenderURL(); 
portletURL.setParameter("tabs1", tabs1); 
%> 
<portlet:renderURL var="addFeedBackURL"> 
<portlet:param name="mvcPath"
  value="/html/workflow/feedback.jsp"/> 
</portlet:renderURL> 
<h4>Kaleo workflow for
  custom Assets</h4> 
<a href="<%=addFeedBackURL%>"
  style="font-weight:bold;font-size:18px;">Add New FeedBack</a><br/><br/> 
<liferay-ui:tabs 
names="Aproved
  Feedback,Pending Feedback" 
portletURL="<%= portletURL %>" 
/> 
<c:choose> 
<c:when test='<%= tabs1.equals("Pending Feedback") %>'> 
<liferay-util:include page="/html/workflow/view_pending_feedback.jsp"
  servletContext="<%= application %>" /> 
</c:when> 
<c:otherwise> 
<liferay-util:include page="/html/workflow/view_approved_feedback.jsp"
  servletContext="<%= application %>" /> 
</c:otherwise> 
</c:choose> | 
view_approved_feedback.jsp
| 
<%@page import="com.liferay.portal.kernel.util.ListUtil"%> 
<%@page import="com.meera.workflow.db.model.Feedback"%> 
<%@page import="com.liferay.portal.kernel.workflow.WorkflowConstants"%> 
<%@page import="com.meera.workflow.db.service.FeedbackLocalServiceUtil"%> 
<%@page import="javax.portlet.PortletURL"%> 
<%@ include
  file="init.jsp"%> 
<liferay-portlet:renderURL varImpl="iteratorURL"> 
<portlet:param name="mvcPath"
  value="/html/workflow/view_approved_feedback.jsp"
  /> 
</liferay-portlet:renderURL> 
<liferay-ui:search-container emptyResultsMessage="there-are-no-students" 
headerNames="FeedBack
  Subject,Message, Stauts" 
iteratorURL="<%=iteratorURL %>" 
delta="10" deltaConfigurable="true"> 
<liferay-ui:search-container-results> 
<% 
List<Feedback>
  feedbackList=
  FeedbackLocalServiceUtil.findByG_S(themeDisplay.getScopeGroupId(),WorkflowConstants.STATUS_APPROVED); 
results=ListUtil.subList(feedbackList,searchContainer.getStart(),
  searchContainer.getEnd()); 
searchContainer.setTotal(feedbackList.size()); 
searchContainer.setResults(results); 
%> 
</liferay-ui:search-container-results> 
<liferay-ui:search-container-row className="Feedback" 
keyProperty="feedbackId" modelVar="currentFeedback"> 
<liferay-ui:search-container-column-text 
name="FeedBack
  Subject" property="feedbackSubject" /> 
<liferay-ui:search-container-column-text 
name="Message" property="feedbackText"
  /> 
<liferay-ui:search-container-column-text name="status"><%=WorkflowConstants.LABEL_APPROVED %></liferay-ui:search-container-column-text> 
</liferay-ui:search-container-row> 
<liferay-ui:search-iterator searchContainer="<%=searchContainer %>"
  /> 
</liferay-ui:search-container> | 
view_pending_feedback.jsp
| 
<%@page import="com.liferay.portal.kernel.workflow.WorkflowDefinitionManagerUtil"%> 
<%@page import="com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil"%> 
<%@page import="com.liferay.portal.kernel.util.ListUtil"%> 
<%@page import="com.meera.workflow.db.model.Feedback"%> 
<%@page import="com.liferay.portal.kernel.workflow.WorkflowConstants"%> 
<%@page import="com.meera.workflow.db.service.FeedbackLocalServiceUtil"%> 
<%@page import="javax.portlet.PortletURL"%> 
<%@ include
  file="init.jsp"%> 
<liferay-portlet:renderURL varImpl="iteratorURL"> 
<portlet:param name="mvcPath"
  value="/html/workflow/view_pending_feedback.jsp"
  /> 
</liferay-portlet:renderURL> 
<liferay-ui:search-container emptyResultsMessage="there-are-no-students" 
headerNames="FeedBack
  Subject,Message, Stauts" 
iteratorURL="<%=iteratorURL %>" 
delta="10" 
deltaConfigurable="true"> 
<liferay-ui:search-container-results> 
<% 
List<Feedback>
  feedbackList=
  FeedbackLocalServiceUtil.findByG_S(themeDisplay.getScopeGroupId(),WorkflowConstants.STATUS_DRAFT); 
results=ListUtil.subList(feedbackList,searchContainer.getStart(),
  searchContainer.getEnd()); 
searchContainer.setTotal(feedbackList.size()); 
searchContainer.setResults(results); 
%> 
</liferay-ui:search-container-results> 
<liferay-ui:search-container-row className="Feedback" 
keyProperty="feedbackId" modelVar="currentFeedback"> 
<liferay-ui:search-container-column-text 
name="FeedBack
  Subject" property="feedbackSubject" /> 
<liferay-ui:search-container-column-text 
name="Message" property="feedbackText"
  /> 
<liferay-ui:search-container-column-text name="status"><%=WorkflowConstants.LABEL_PENDING %></liferay-ui:search-container-column-text> 
</liferay-ui:search-container-row> 
<liferay-ui:search-iterator searchContainer="<%=searchContainer %>"/> 
</liferay-ui:search-container> | 
feedback.jsp
| 
<%@page import="com.liferay.portal.kernel.servlet.SessionErrors"%> 
<%@page import="com.liferay.portal.kernel.servlet.SessionMessages"%> 
<%@page import="com.liferay.portal.kernel.portlet.LiferayWindowState"%> 
<%@page import="javax.portlet.ActionRequest"%> 
<%@ include
  file="init.jsp"%> 
<portlet:actionURL var="submitFeedBack"
  windowState="<%=LiferayWindowState.NORMAL.toString()%>"
  name="submitFeedback"> 
</portlet:actionURL> 
<a href="<portlet:renderURL
  />">«Home</a> 
<div class="separator"></div> 
<fieldset> 
<legend>Feedback Form</legend> 
<c:if test='<%= SessionMessages.contains(renderRequest.getPortletSession(),"feedback-submit-success")%>'> 
<liferay-ui:success key="feedback-submit-success"
  message="Feedback has been submited successfully."
  /> 
</c:if> 
<c:if test='<%=
  SessionMessages.contains(renderRequest.getPortletSession(),"workflow-not-enabled")%>'> 
<liferay-ui:success key="workflow-not-enabled"
  message="Feedback not enabled with workflow please enable
  workflow." /> 
</c:if> 
<c:if test='<%=
  SessionErrors.contains(renderRequest.getPortletSession(),"feedback-submit-failed")%>'> 
<liferay-ui:success key="feedback-submit-failed"
  message="There is problem of submit feedback please try
  again.." /> 
</c:if> 
<aui:form action="<%=submitFeedBack%>"
  method="post" name="feedbackForm"> 
<aui:layout> 
<aui:column> 
<aui:input    label="Feedback Subject" name="feedbackSubject" id="feedbackSubject" type="text" style="width:600px;height:20px;"> 
<aui:validator name="required"
  /> 
</aui:input> 
</aui:column> 
</aui:layout> 
<aui:layout> 
<aui:input name="feedbackMessage"
  id="feedbackMessage" label="Feedback Message" type="textarea" style="width:600px;height:100px;"> 
<aui:validator name="required"
  /> 
</aui:input> 
<span style=" float: left;">Characters Left </span><p id="<portlet:namespace/>textCounter"></p> 
</aui:layout> 
<aui:layout> 
<aui:column> 
  
</aui:column> 
</aui:layout> 
<aui:layout> 
<aui:column> 
<aui:button type="submit"
  value="Submit Feedback" name="submit" 
></aui:button> 
</aui:column> 
</aui:layout> 
</aui:form> 
</fieldset><aui:script> 
AUI().use('aui-char-counter', function(A) { 
new A.CharCounter({ 
counter : '#<portlet:namespace/>textCounter', 
input : '#<portlet:namespace/>feedbackMessage', 
maxLength : 75, 
on : { 
maxLength : function(event) { 
alert('The max length
  limit was reached'); 
} 
} 
}); 
}); 
</aui:script> | 
view_feedbck.jsp
| 
<%@page import="com.meera.workflow.db.model.impl.FeedbackBaseImpl"%> 
<%@page import="com.meera.workflow.db.service.FeedbackLocalServiceUtil"%> 
<%@page import="com.liferay.portal.kernel.servlet.SessionMessages"%> 
<%@page import="com.liferay.portal.kernel.portlet.LiferayWindowState"%> 
<%@page import="javax.portlet.ActionRequest"%> 
<%@page import="com.meera.workflow.db.model.Feedback"%> 
<%@ include
  file="init.jsp"%> 
<% 
Feedback feedback=null; 
if(request.getAttribute("feedBackObject")!=null) 
feedback =
  (Feedback)request.getAttribute("feedBackObject"); 
%> 
<c:if test='<%=feedback!=null%>'> 
<h2><%=feedback.getFeedbackSubject()%></h2> 
<br/> 
Message: 
<div> 
<%=feedback.getFeedbackText()%> 
</div> 
</c:if> | 
Usage
of Portlet
Download portlet from download link there you can see source
and war file and .war file you can deploy into your Liferay portal. Make sure
your portal version. You can also use source to create war file and deploy into
your portal server.
Portlet available under “workflow” category you can add to your desire page.
Enable
Workflow to Feedback Asset/Portlet
Please go through the following post for better understanding
to use workflow in Liferay.
Now Login as Portal Administrator and go to Control
panel there click on Workflow link in the configuration section.
In the Workflow configuration go to default
workflow configuration tab there you can see the Feedback Asset in
the list for that select workflow level and save the configuration so that Feedback
asset is now enable with given workflow
Now go the page where you drag and drop the Feedback
Workflow portlet there you can find Add New Feedback Link and
click on that you can see feedback form.
Now fill the form and save it then the submission
going through the workflow process.
We already enable Single Level Approval so login as content
reviewer role so that you can find feedback entry in his/her workflow
task List there he/she can approve /Reject.
Click on My Account 
In the my workflow task list you can see Feedback
Submission and we already know this is role based task so first we need to assign
to me and then we can approve the task
Once you assign to you then task will come under Assign
to me section there you can approve/reject the task
This is how you can complete your feedback submission
through workflow.
Now go to feedback portlet there you can see Approved
Feedback List and Pending feedback List
The
following approved feedback list
The
following so Pending feedback List
Author
 

 
 
 Posts
Posts
 
 
