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