cancel
Showing results for 
Search instead for 
Did you mean: 

Liferay Portlet

corch
Champ in-the-making
Champ in-the-making
Hi guys,

I've played a little bit around with the Activiti integration for Liferay but am failing on my current task.

I'm about to write a portlet that will follow a workflow and extract some information out of it.
So I tried the following code to get the ProcessEngine and want to extract the information.


        import org.activiti.engine.ProcessEngine;
        import org.activiti.engine.ProcessEngines;
        import org.activiti.engine.RepositoryService;
        …
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repServ = processEngine.getRepositoryService();


But when I integrate the portlet an error is thrown:

09:45:28,413 ERROR [http-bio-8080-exec-12][render_portlet_jsp:132] null
java.lang.NoClassDefFoundError: Could not initialize class org.activiti.engine.ProcessEngines
   at sonia.portal.proxportlet.EmptyPortlet.doView(EmptyPortlet.java:113)
   at javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:328)
   at javax.portlet.GenericPortlet.render(GenericPortlet.java:233)
   at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:103)
   at com.liferay.portlet.ScriptDataPortletFilter.doFilter(ScriptDataPortletFilter.java:55)
   at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:100)
   at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:64)
   at com.liferay.portal.kernel.servlet.PortletServlet.service(PortletServlet.java:112)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
   at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
   at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:119)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
   at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
   at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:605)
   at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:544)
   at com.liferay.portlet.InvokerPortletImpl.invoke(InvokerPortletImpl.java:583)
   at com.liferay.portlet.InvokerPortletImpl.invokeRender(InvokerPortletImpl.java:656)


The activiti-engine-5.18.jar is located inside the WEB-INF/lib folder of the portlet. I'm using the Liferay 6.2 ga4 CE bundled with Tomcat.

Thanks for any help 😃
4 REPLIES 4

vasile_dirla
Star Contributor
Star Contributor
Hi,
considering this exception:
<code>
java.lang.NoClassDefFoundError: Could not initialize class org.activiti.engine.ProcessEngines
</code>
it's clear that this class is not exposed to the proper class loader. (I have the feeling that the current class loader is set to portal class loader at that point.. but without debugging is just a guess)

I'm sure if you will put the activiti.jar in parent class loader (tomcat's global classLoader), then it will be visible and will work but since  activiti will be used only inside this portlet the best way will be to put the activiti.jar into your portlet's class loader.

will be very useful if you could post here the code of your portlet. (or a similar posrlet where we can see the behaviour)

corch
Champ in-the-making
Champ in-the-making
Hi Vasile,

thanks for your quick response.

So I put the jar inside the global classLoader but there is no difference to my prevous attempt.

This is an example portlet written by a colleague of mine. I'm just playing around with it a little bit to get comfortable with the portlet creation.
It will display the first page of the german Wikipedia.

So in the doView method I'm trying to get the ProcessEngine

<code>
package sonia.portal.proxportlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletURL;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ResourceURL;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;

/**
*
* @author simon
*/
public class EmptyPortlet extends GenericPortlet {
    private static String extractEncoding(URLConnection c){
        {
            String contentEncoding = c.getContentEncoding();
            String contentType = c.getContentType();
            if(contentEncoding!=null)return contentEncoding;
           
            int pos = contentType==null?0:contentType.indexOf("charset=");
            if(pos>=0){
                String part = contentType.substring(pos+8);
                pos = part.indexOf(";");
                if(pos>=0)
                    part = part.substring(0,pos);
                return part;
            }
        }
        return "UTF-8";
    }
    private void replaceUrl(Node node, RenderResponse resp,boolean resource){
        String nodeValue = node.getNodeValue();
        if(nodeValue.startsWith("/") && !nodeValue.startsWith("//")){
            if(resource){
                ResourceURL ru = resp.createResourceURL();
                ru.setParameter("relurl", nodeValue);
                node.setNodeValue(ru.toString());
                return;
            }else{
                PortletURL ru = resp.createRenderURL();
                ru.setParameter("relurl", nodeValue);
                node.setNodeValue(ru.toString());
                return;
            }
        }
        node.setNodeValue(nodeValue);
    }
    private void replaceUrls(Document doc, RenderResponse resp){
        NodeList nl = doc.getElementsByTagName("a");
        for(int i=0,n=nl.getLength();i<n;++i){
            Node node = nl.item(i).getAttributes().getNamedItem("href");
            if(node!=null)
                replaceUrl(node, resp, false);
        }
        nl = doc.getElementsByTagName("img");
        for(int i=0,n=nl.getLength();i<n;++i){
            Node node = nl.item(i).getAttributes().getNamedItem("src");
            if(node!=null)
                replaceUrl(node, resp, true);
        }
    }
    @Override
    protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
        System.err.println("doView");
       
        String url = "https://de.wikipedia.org/";
       
        {
            String relUrl = request.getParameter("relurl");
            if(relUrl!=null && !relUrl.isEmpty()){
                url = "https://de.wikipedia.org'+relUrl;
            }
        }
       

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repServ = processEngine.getRepositoryService();
        System.out.println("Number of process definitions: " + repServ.createProcessDefinitionQuery().count());
       
       
        URL u = new URL(url);
        URLConnection c = u.openConnection();
        InputStream is = c.getInputStream();
        response.setContentType("text/html");
       
       
        String enc = extractEncoding©;
        //IOUtils.copy(is, os);
        Tidy tidy = new Tidy();
        tidy.setQuiet(true);
        tidy.setErrout(NullWriter.PRINTER);
        tidy.setInputEncoding(enc);
        tidy.setOutputEncoding(response.getCharacterEncoding());
        Document doc = tidy.parseDOM(is, null);
        replaceUrls(doc,response);
        OutputStream os = response.getPortletOutputStream();
        tidy.pprint(doc, os);
        IOUtils.closeQuietly(os);
        IOUtils.closeQuietly(is);
    }

    @Override
    public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException {
        System.err.println("serveResource");
        String url = "https://de.wikipedia.org/wiki/Portlet";
        {
            String relUrl = request.getParameter("relurl");
            if(relUrl!=null && !relUrl.isEmpty()){
                url = "https://de.wikipedia.org'+relUrl;
            }
        }
        URL u = new URL(url);
        URLConnection c = u.openConnection();
        InputStream is = c.getInputStream();
        OutputStream os = response.getPortletOutputStream();
        response.setContentType(c.getContentType());
        IOUtils.copy(is, os);
        IOUtils.closeQuietly(os);
        IOUtils.closeQuietly(is);
    }
   
}
</code>

corch
Champ in-the-making
Champ in-the-making
Hello again 😃

The approach I followed was simply wrong. Instead of getting an instance of the ProcessEngine I had to use the build in functions provided by the Liferay API.

So this did the trick:
<code>
    JournalArticle journalArticle = JournalArticleLocalServiceUtil.getArticle(entryClassPK);
    System.out.println(journalArticle.getStatus());
</code>

'entryClassPK' is the ID of the corresponding document.

Thanks 😃

vasile_dirla
Star Contributor
Star Contributor
ok, so you solved it.
I's not necessary to create a new ProcessEngine  instance when doView is called.

in my opinion if will ever want to instantiate the process engine into a portlet application then you have to initialize the engine inside a web application listener. (a single process engine instance for all the portlets in the same application)

or in the portlet's init method. (which is called only once when the portlet is loaded into the portlet container)
(if you initialize the engine in the doView method then it will slow down the first render of the portlet)

But It's good you solved your issue.
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.