kaleo configuration for custom portlet in liferay 6.0 EE.

Step1 : Add following reference and column to your service.xml (service in which you would like add workflow),out of these some of fields must be there which will help in mapping between workflow tables and your custom table.

<column name="resourcePrimKey" type="long"></column>

<column name="title" type="String"></column>

<column name="status" type="int"></column>

<column name="statusByUserId" type="long"></column>

<column name="statusByUserName" type="String"></column>

<column name="statusDate" type="Date"></column>

<!-- Finder methods -->

<finder name="R_S" return-type="Collection">

<finder-column name="resourcePrimKey"></finder-column>

<finder-column name="status"></finder-column>

</finder>

<reference package-path="com.liferay.portal" entity="WorkflowInstanceLink"></reference>

<reference package-path="com.liferay.portlet.asset" entity="AssetEntry"></reference>

<reference package-path="com.liferay.portlet.social" entity="SocialActivity"></reference>

 

Step 2 :Build service to make sure there is no compile time error.

 

Step 3: Once you Confirm with service just add following line in liferay-portlet.xml <portlet> tag on which you wish to apply workflow.

 

<workflow-handler>path</workflow-handler>

<asset-renderer-factory>path</asset-renderer-factory>

 

- path : This is path of your own workflow handler class and your own

AssetRendererFactory handler class

- Note : This tag should before initialize of portlet.

 

E.x

<asset-renderer-actory>

com.liferay.admin.asset.ArticleAssetRendererFactory

</asset-renderer-factory>

<workflow-handler>com.liferay.workflow.ArticleWorkflowHandler</workflow-handler>

 

Step 4: You need to extend com.liferay.portal.kernel.workflow.BaseWorkflowHandler class and override four abstract method.

 

  • String getClassName()
  • String getType(Locale locale)
  • Object updateStatus(int status,Map workflowContext)
  • String getIconPath(ThemeDisplay themeDisplay)

 

public class ArticleWorkflowHandler extends BaseWorkflowHandler

{

----------

--------

-----------

}

Note : Here one thing is very important updateStatus() method called another method which you gonna developed in Step5.

 

E.x

public Object updateStatus(int status, Map<String, Serializable> workflowContext)

{

return DemoLocalServiceUtil.updateStatus(userId, resourcePrimKey, status,      serviceContext);

}

 

Step 5: Now you need to implement one method called updateStatus() in you LocalServiceImpl class. which will return object of your model class.

 

E.x

public class DemoLocalServiceImpl extends DemoLocalServiceBaseImpl

{

public Demo updateStatus(long userId, long resourcePrimKey, int status,ServiceContext serviceContext)

{

User user = userPersistence.findByPrimaryKey(userId);

Date now = new Date();

// Article

Demo dempObj = null;

dempObj.setStatus(status);

dempObj.setStatusByUserId(user.getUserId());

dempObj.setStatusByUserName(user.getFullName());

dempObj.setStatusDate(serviceContext.getModifiedDate(now));

demoPersistence.update(dempObj, false);

if (status != WorkflowConstants.STATUS_APPROVED)

{

return dempObj;

}

return dempObj;

}

}

}

Step6: You need to extend com.liferay.portlet.asset.model.BaseAssetRendererFactory class and override abstract method.

 

  • String getClassName()
  • String getType(Locale locale)
  • Object getAssetRenderer(long classPK, int type)

E.x

public class ArticleAssetRendererFactory extends BaseAssetRendererFactory

{

----------

--------

public static final String CLASS_NAME = Article.class.getName();

public static final String TYPE = "article";

@Override

public AssetRenderer getAssetRenderer(long classPK, int type)

throws PortalException, SystemException {

// TODO Auto-generated method stub

int status = WorkflowConstants.STATUS_ANY;

if (type == TYPE_LATEST_APPROVED) {

status = WorkflowConstants.STATUS_APPROVED;

}

Article article = ArticleLocalServiceUtil.getLatestArticle(

classPK, status);

return new ArticleAssetRenderer(article);

}

     }

Note : Here one thing is ArticleAssetRenderer Class which you gonna developed in Step7.

 

Step7: Now you need to create one class called ArticleAssetRenderer and extends BaseAssetRenderer and override 7 abstract method.

 

  • long getClassPK()
  • long getGroupId()
  • String getSummary()
  • String getTitle()
  • long getUserId()
  • String render(RenderRequest renderRequest,
  • RenderResponse renderResponse, String template)

E.x.

public class ArticleAssetRenderer extends BaseAssetRenderer

{

----------

--------

----------

public String render(

RenderRequest renderRequest, RenderResponse renderResponse,

String template) throws Exception {

if (template.equals(TEMPLATE_FULL_CONTENT)) {

   return "/admin/asset/fullcontent.jsp";

}else {

return null;

}

}

}

 

 

 

Step8: Now Deploy service and portlet you will find out your asset in control panel as showing below .now you can apply any definition on that.

 

 

Step9: Start workflow

  • Now you need to start Workflow at the time of add content there.
  • You have to write following method in your addContent() and updateContent() in your ***LocalServiceImpl class.

 

  • assetEntryLocalService.updateEntry(

userId, article.getGroupId(), Article.class.getName(),

article.getClassPK(), article.getUuid(), assetCategoryIds,

assetTagNames, article.isApproved(), null, null, null, null,

ContentTypes.TEXT_HTML, article.getTitle(),

article.getDescription(), null, null, 0, 0, null, false);

  •  WorkflowHandlerRegistryUtil.startWorkflowInstance(

     user.getCompanyId(), groupId, userId, Demo.class.getName(),

     resourcePrimKey, article, serviceContext);

-E.x

public class ArticleLocalServiceImpl extends ArticleLocalServiceBaseImpl{

   public Article addArticle(long userId, long parentResourcePrimKey, String title,String content, String description, int priority, String dirName, ServiceContext serviceContext)

    throws PortalException, SystemException      

   {

User user = userPersistence.findByPrimaryKey(userId);

long groupId = serviceContext.getScopeGroupId();

long articleId = counterLocalService.increment();

long resourcePrimKey = counterLocalService.increment();

Article article = articlePersistence.create(articleId);

articlePersistence.update(article, false);

    // Asset

     updateAsset(

     userId, article, serviceContext.getAssetCategoryIds(),

     serviceContext.getAssetTagNames());

    // Workflow

     WorkflowHandlerRegistryUtil.startWorkflowInstance(

     user.getCompanyId(), groupId, userId, Article.class.getName(),

     resourcePrimKey, article, serviceContext);

return article;

}

public void updateAsset(long userId, Article article, long[] assetCategoryIds,String[] assetTagNames)throws PortalException, SystemException {

   assetEntryLocalService.updateEntry(userId, article.getGroupId(), Article.class.getName(),article.getClassPK(), article.getUuid(), assetCategoryIds,assetTagNames, article.isApproved(), null, null, null, null,ContentTypes.TEXT_HTML, article.getTitle(), article.getDescription(), null, null, 0, 0, null, false);

}

}

Blogues
Hi Priti,
good Article, i thought about asking a question in forum for long time... i find it this as a right time.....

i am looking for some article regarding liferay api on workflow... which i can build built on my custom plugin. for example instead of kaleo workflow, if i want to any other like jbpm or activi or any other workflow to integrated what are basic steps and api i should use... some kind of steps must be there.....

Hope u understand my question.
Hi Priti,
Thanx for this great post.
Actually i had some issue regarding this.
a)I am getting an error while adding <finder> tag in service.xml
b)I was unable to define the abstact method in ArticleWorkflowHandler class, so this will be a great help if you post a dummy code for this so that i can get an idea.

and if possible please mail me.
id:babu.nandan.biswal@gmail.com

Thank You
Regards
Babu Nandan Biswal
Hi
I have a confusion that the method updateStatus is implemented in Impl class while accessed in handler using LocalServiceUtil.updateStatus() . How will it work?
i get an exception because there is no parameterized constructor in AssetRenderer while we are calling it in the AssetRendererFactory.
Also where is "/admin/asset/fullcontent.jsp"?? We need to create it?