« 返回到 FrontPage

Adding Piwik Web Analytics to Liferay

Introduction #

Piwik.org is a free, open source, self-hosted web analytics platform that can provide valuable information on your site's visitors. To use piwik on a normal site, you grab a chunk of generated javascript and paste it into your site's pages.

Liferay, as we all know, is a horse of a different color. Using piwik in Liferay is difficult because:

  1. Liferay pages are not static.
  2. Liferay pages are generated from Velocity.
  3. Information necessary for calling piwik is not really available at necessary points in Liferay.

Purpose #

To begin with, I certainly didn't need or want to be able to leverage all possible piwik functionality. My only goal was to be able to track hits on my navigatable pages of my Liferay-based site.

So if you implement everything I've outlined below, you'll be able to track page views of your portal using just a custom jar, some additions to portal-ext.properties, a new servlet filter for the ROOT web application (Liferay), and a small addition to your portal-normal.vm template.

Architecture #

Before diving into the changes, a brief note about the architecture I went with.

First of all, I knew that information from the original incoming HttpServletRequest needed to be captured and stored so it would be available when it came time to call the Piwik server. Using Liferay auditing as a model, I created a ThreadLocal class to hold a POJO called PiwikVisitorInfo. This POJO has the necessary member fields to hold all of the information piwik would need, from a visitor perspective, to track page views. To populate and maintain the POJO, I created a filter that is inserted into the normal Liferay filter chain. Liferay 6.1 will allow using a hook to deploy a servlet filter, but as I'm still on 6.0 the filter must be added manually.

To handle the minor configuration changes, I've defined some new properties that must be set in portal-ext.properties for the Piwik site id (used to tell Piwik that the page views were on one site or another) and the Piwik server (so it wouldn't need to be hard-coded anywhere).

To make pieces of the code available to the velocity templates, I needed to inject some Spring beans into Liferay's Spring context. To do this I've included an XML file with the Spring bean definitions; another change to portal-ext.properties is necessary to ensure it gets loaded at server startup.

There is some code involved. This code is bundled into a jar and must be put into the ROOT/WEB-INF/lib folder. You can either manually copy this jar in or you can use an EXT plugin to deploy it.

Quick Start #

Basically you're going to do the following:

  1. Download the piwik-liferay.jar file and get it in the ROOT/WEB-INF/lib directory.
  2. Edit ROOT/WEB-INF/web.xml (for CE) or ROOT/WEB-INF/liferay-web.xml (for EE) to add the filter.
  3. Edit ROOT/WEB-INF/classes/portal-ext.properties to add the new properties, enable the filter, and pull in the piwik.spring.xml file during Liferay startup.
  4. Restart your app server.
  5. Edit the portal-normal.vm file of your custom theme to add a few lines and deploy it.

Download the piwik-liferay.jar file #

I'm attaching the precompiled jar file to this wiki page. I'll also include the Eclipse project (zipped w/ source) if you want to check it out.

Download the piwik-liferay.jar file and put it into the ROOT/WEB-INF/lib directory. It may be possible to put it in the global lib directory (i.e. Tomcat's lib/ext directory), although I haven't tried it. If you want to deploy the jar using the normal Liferay way, you'll need to create an EXT plugin and put the jar into the EXT project's docroot/WEB-INF/ext-lib/portal directory and deploy the EXT plugin to Liferay.

Adding the Servlet Filter #

The piwik servlet filter will be invoked for many incoming requests. Adding the filter is a manual process outlined below.

If you're running CE, you're going to edit ROOT/WEB-INF/web.xml. If you're running EE, you're going to edit ROOT/WEB-INF/liferay-web.xml. The changes are the same regardless of which file you're editing.

You're going to be adding two XML stanzas to the appropriate XML file.

The first stanza below defines the filter:

<filter>
  <filter-name>Piwik Filter</filter-name>
  <filter-class>org.piwik.liferay.servlet.filter.PiwikServletFilter</filter-class>
  <init-param>
    <param-name>url-regex-ignore-pattern</param-name>
    <param-value>^/html/.+\.(css|gif|html|ico|jpg|js|png)(\?.*)?$</param-value>
  </init-param>
</filter>

The next stanza defines the filter mapping:

<filter-mapping>
  <filter-name>Piwik Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

When inserting these two stanzas into the XML file, be sure to put them in the appropriate locations in the file. For those that don't know, add the <filter /> stanza where you see other <filter /> tags, and the <filter-mapping /> stanza around the other <filter-mapping /> tags in the file.

Portal Properties #

There are some portal-ext.properties file additions that you'll need to make:

# Enable the Piwik servlet filter
org.piwik.liferay.servlet.filter.PiwikServletFilter=true

# Define the URL for your piwik server
# piwik.url=http://piwik.example.com/piwik/
piwik.url=http://localhost/piwik/

# Define the site id this Liferay instance will report page hits to.
# Sites should already be defined in the piwik admin interface.
piwik.site.id=2

# Add the piwik-spring.xml to the list of xml files to load when Liferay starts
spring.configs=\
  [see note],\
  META-INF/piwik-spring.xml

Note: For the spring.configs guy, you're actually overriding the default value in portal.properties. You're going to want to copy the current value from portal.properties and use for this property, you're just going to add the META-INF/piwik-spring.xml to the end.

Adding Tracking to portal-normal.vm #

After restarting your application server, you'll now be ready to make changes to your theme's portal-normal.vm file to add page view tracking.

Open the portal-normal.vm file in the _diffs/templates directory of your custom theme. Just above the closing </body> tag at the bottom of the page, add the following:

#set( $piwikTracker = $utilLocator.findUtil("org.piwik.liferay.PiwikTracker") )
#if( $piwikTracker)
  #set( $piwikResult = $piwikTracker.trackPageView($the_title) )
#end

Deploy your theme and start browsing pages. On your piwik server, you should now see some hits coming from your Liferay box.

Visitor Custom Variables #

Piwik supports using visitor custom variables, or variables that are defined at the visitor level. The Liferay piwik implementation defines and populates four custom variables:

  • realUserId The user id logged into the system.
  • realUserName The user's real name.
  • userId The effective user id (when impersonating a user, this is the id of the impersonated user).
  • userName The effective user name (when impersonating a user, this is the name of the impersonated user).

Other Features Implemented But Not Tested #

The piwik-liferay jar has other features implemented, but they have not been tested:

  • Page-level details, including support for page custom variables.
  • Other types of tracking:
    • Link tracking
    • Download tracking
    • Goal tracking
    • E-Commerce tracking

Notes #

Cookies #

The normal way of using piwik is to include a javascript file, piwik.js, on each page being tracked. This script will actually add some cookies to the users browser, and these cookies are sent to the piwik server on each request.

The cookies include data such as the visitor id, the browser window size, and some of the browser plugins that may be installed (such as quicktime, java, flash, etc.).

Since the code I've presented is not running in the browser, these cookies are not defined, they're not sent, and they're not tracked in piwik.

You could, if needed, manually include the piwik.js file, but this may have side effects that interfere with the overall portal page.

Locally we built a simple javascript method, executed when the page is ready, to sniff for the plugins and set the appropriate cookies. The method is based loosely off of the piwik.js code.

Also, after piwik is called and it has third party cookies enabled, a tracking cookie will be returned by piwik. Again, since this implementation is not running in the browser, the tracking cookie does not get sent back to the browser and the information is lost.

For this case, locally we modified the PiwikTracker interface to return a string of javascript that will set the cookie (using jQuery's cookie.js support). Our portal_normal.vm template then becomes:

#set( $piwikTracker = $utilLocator.findUtil("org.piwik.liferay.PiwikTracker") )
#if( $piwikTracker)
  #set( $piwikResult = $piwikTracker.trackPageView($the_title) )
  #if( $piwikResult)
$piwikResult
  #end
#end

When the piwik result is valid, it will be included in the rendered page, the javascript will be invoked in the browser, and the tracking cookie will be set and included with all subsequent calls to the server (thus allowing you to track on returning visitors).

Note that the tracking cookie name is defined in the global piwik configuration (global.ini.php) and the default value does not match the cookie name the code is looking for (a string that contains "id.#.", where the # is the site id), so you'll probably need to make modifications to the code to match the global.ini.php configuration before using it.

Page Info #

Piwik actually uses two different types of information: visitor information and page information. The visitor information is populated by the PiwikServletFilter and ensures that the visitor information is correct.

For page information, the PiwikTracker interface includes a method, getPageInfo(). The getPageInfo() method returns an instance of PiwikPageInfo that you can use to supply additional information such as goal campaigns, page custom variables, and forced timestamps.

To use this in Velocity, you would have code like:

#set( $piwikTracker = $utilLocator.findUtil("org.piwik.liferay.PiwikTracker") )
#if( $piwikTracker)
  #set( $piwikPage = $piwikTracker.getPageInfo() )
  #if( $piwikPage)
    #set( $piwikPage = $piwikPage.addCustomVariable("myPageVar","value") )
    #set( $piwikPage = $piwikPage.setGoalCampaignName("My Campaign") )
  #end
  #set( $piwikResult = $piwikTracker.trackPageView($the_title, $piwikPage) )
#end

The PiwikPageInfo object returns a reference to itself for all setters so it can be safely used in velocity.

The PiwikPageInfo object, when populated, is added as the last argument for all of the tracking methods.

Piwik Release Inconsistencies #

Finally, it is important to note that it seems like Piwik.org does not keep any of their code releases in sync. The piwik server code seems to be developed and maintained separately from the PiwikTracker.php code (for tracking within a PHP-based site) and is certainly out of sync with the Java tracker code available on the site.

So while what I've provided will work as-is for basic page tracking, some of the code will require some tweaking on your end to be able to use 100% of the features. You'll probably have to access not only the java code, but the piwik source (including the piwik.js file and possibly core/Tracker.php and core/Tracker/Visit.php) and PiwikTracker.php to identify what changes need to be made.

References #

First, this implementation would not have been possible without some information from the piwik.org site, specifically some java code I downloaded from Piwik Ticket 2172 and Piwik Ticket 3151. The code had to be significantly refactored (the posted code was intended to be added to a JSP page), but it was a great starting point.

Also crucial was the Piwik Tracking API page for documenting the tracking API (including changes made in newer versions of the code that have not yet been replicated into the java tracker).

RELEASES #

I've just uploaded the piwik-liferay-1.1 stuff. You should be able to use this in place of the 1.0 (unlabeled) versions.

1.0 - 07/20/2012 #

Initial release and Wiki page created.

1.1 - 07/21/2012 #

1.1 includes the following:

  1. Change for the browser info cookie name.
  2. Adds a PiwikTrackerUtil class (similar to the Liferay Service Builder's XxxLocalServiceUtil classes) so external plugins can access the PiwikTracker instance the portal is using.
  3. Add in the code for the E-Commerce support in the latest version of PiwikTracker.php script.
  4. Tweaks as to how the piwik visitor id is handled.
4 附件
24966 查看
平均 (1 投票)
满分为 5,平均得分为 4.0。
评论
讨论主题回复 作者 日期
Being able to use Piwik on Liferay projects... Julien Moumné 2012年7月31日 下午12:57
Thanks for sharing this... Jay Patel 2012年8月23日 上午8:23
I chose server-side tracking for one simple... David H Nebinger 2012年10月23日 上午5:57
Thank you for this invaluable documentation to... Patrick Wolf 2013年3月13日 上午11:27
Well, this is not an officially blessed project... David H Nebinger 2013年3月13日 下午12:00
Greetings to all I've tried following your... g p 2013年4月1日 上午2:06
InitializingBean is part of the spring... David H Nebinger 2013年4月1日 上午7:27
So, lets take it step by step: 1. Download the... g p 2013年4月2日 上午5:01
How does one modify this implementation for... Jozef Sabo 2013年4月4日 上午1:35
Hi Jozef , do you have any news about plugin... Riccardo Martini 2013年6月3日 上午7:10
I have got two questions. What is the license... Marek Begowski 2013年6月7日 上午2:44
Piwik is free software under the licence GPL... Patrick Wolf 2013年6月7日 上午3:24
Help yourself, my friend! David H Nebinger 2013年6月7日 上午10:29
Hello Sir.. I used Liferay 6.1.1 CE GA2... Pradip A Bhatt 2013年6月26日 上午5:59
Hi, Did you find the solution ?, Please share lavanya dot r 2013年8月6日 下午11:22
Hi, I can notice a typo in your... Patrick Wolf 2013年6月26日 上午7:39
Hi, I can notice a typo in your... Patrick Wolf 2013年6月26日 上午7:40
Hi, David I have done all stuff described... Bolat Kazybayev 2013年8月21日 上午2:54
I am using a Liferay Community Edition 6.1.1 CE... Bolat Kazybayev 2013年8月21日 上午2:56
@Bolat Kazybayev for Liferay 6.1.1 CE GA2 make... Ankit Pancholi 2013年10月30日 上午3:15
Hi Ankit, I am also getting the same exception.... Vivek Sharma 2014年8月25日 上午6:41
Hi friends, I am trying to integrate Piwik Web... Surodip Patra 2013年12月3日 上午2:25

Being able to use Piwik on Liferay projects will come in very handy indeed, thanks for this contribution!

I however have a hard time figuring-out why you decided to use server side tracking.

Could you elaborate on the rationales behind using server side over client side tracking?
在 12-7-31 下午12:57 发帖。
Thanks for sharing this...
在 12-8-23 上午8:23 发帖。
I chose server-side tracking for one simple reason: Our server hosting our piwik environment is internal-only; clients hitting our site would not be able to communicate w/ the piwik system.

I'm gathering metrics that we use internally. They're not for advertising purposes or any sort of nefarious things. We just want to see where people spend most of their time, our effectiveness at promoting new functionality, determining location of the visitors to see if we need to focus our localization strategy, ...

Google Analytics is, of course, an alternative which you can implement. and since GA is on the net you can implement client side analytics.

Or if your own Piwik server is on the internet, you can use client side tracking there, too. For that, you'd just be following the instructions on Piwik's site to embed the tracking javascript into your portal_norma.vm file and you should be good to go...
在 12-10-23 上午5:57 发帖。
Thank you for this invaluable documentation to integrate Piwik into Liferay. I am currently looking for an alternative to Google analytics and Piwik would suit my needs. Will there be updates of the jar file and is there a community with which we can contribute to enhance it for Liferay?
在 13-3-13 上午11:27 发帖。
Well, this is not an officially blessed project for Liferay. I needed analytics support and could not leverage GA. In building out the piwik support, I contributed it back in. It is currently working on our end. It has fallen behind some of the development for the java API on the piwik site.

As far as contributing, right now I think this page is the only option...
在 13-3-13 下午12:00 发帖。
Greetings to all

I've tried following your instructions, but it keeps failing with
==================================
org.springframework.beans.factory.CannotLo­adBeanClassException: Error loading class [org.piwik.liferay.impl.PiwikServerConnectorImpl] for bean with name 'org.piwik.liferay.PiwikServerConnector' defined in class path resource [META-INF/piwik-spring.xml]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/springframework/beans/factory/InitializingBean
==============================­====

Do you know what could it be?
在 13-4-1 上午2:06 发帖。
InitializingBean is part of the spring framework, and spring should be available to the ROOT web application. So basically it should be there and you should not be getting a NoClassDefFoundError for it, and I'm not sure why you would be getting it.
在 13-4-1 上午7:27 发帖。
So, lets take it step by step:

1. Download the piwik-liferay.jar file and placing it correctly...
I cant imagine myself doing this the wrong way....

2. Adding the Servlet Filter
Just plain copy-paste procedure...

3. Portal Properties
a. Well maybe there lies my error! The only .properties file that i can find is portal-setup-wizard.properties, so i think we are talking about the same file when you say portal-ext.properties?
b. What i am copying-pasting is as follows:

# Add the piwik-spring.xml to the list of xml files to load when Liferay starts
spring.configs=\
META-INF/base-spring.xml,\
\
META-INF/hibernate-spring.xml,\
META-INF/infrastructure-spring.xml,\
META-INF/management-spring.xml,\
\
META-INF/util-spring.xml,\
\
META-INF/jpa-spring.xml,\
\
META-INF/executor-spring.xml,\
\
META-INF/audit-spring.xml,\
META-INF/cluster-spring.xml,\
META-INF/editor-spring.xml,\
META-INF/jcr-spring.xml,\
META-INF/ldap-spring.xml,\
META-INF/messaging-core-spring.xml,\
META-INF/messaging-misc-spring.xml,\
META-INF/mobile-device-spring.xml,\
META-INF/notifications-spring.xml,\
META-INF/poller-spring.xml,\
META-INF/rules-spring.xml,\
META-INF/scheduler-spring.xml,\
META-INF/scripting-spring.xml,\
META-INF/search-spring.xml,\
META-INF/workflow-spring.xml,\
\
META-INF/counter-spring.xml,\
META-INF/mail-spring.xml,\
META-INF/portal-spring.xml,\
META-INF/portlet-container-spring.xml,\
META-INF/staging-spring.xml,\
META-INF/virtual-layouts-spring.xml,\
\
#META-INF/dynamic-data-source-spring.xml,\
#META-INF/shard-data-source-spring.xml,\
#META-INF/memcached-spring.xml,\
#META-INF/monitoring-spring.xml,\
\
META-INF/ext-spring.xml,\
META-INF/piwik-spring.xml

Can you see anything wrong about this?

Thanks in advance.
在 13-4-2 上午5:01 发帖以回复 David H Nebinger
How does one modify this implementation for Liferay 6.1.? I understand that the filter definition has to be converted to a hook, which I've done. Do I need to split the Spring portion of the code away so it still will be loaded when the server starts?
在 13-4-4 上午1:35 发帖。
Hi Jozef ,
do you have any news about plugin hook version ?

Thanks

riccardo
在 13-6-3 上午7:10 发帖以回复 Jozef Sabo
I have got two questions. What is the license of piwik-liferay.jar? Can I use it commercially? Can I make changes to the code?
在 13-6-7 上午2:44 发帖。
Piwik is free software under the licence GPL v3. There should normally be no problem regarding the jar archive provided here which uses the official Piwik java API and is customed for Liferay. You may ask David who developed it for his own needs and shared it with the community as an alternative to Google Analytics.
在 13-6-7 上午3:24 发帖以回复 Marek Begowski
在 13-6-7 上午10:29 发帖以回复 Marek Begowski
Hello Sir..
I used Liferay 6.1.1 CE GA2 Version.
I download attachment. then make related changes in ROOT/WEB-INF/web.xml and add this one.

<filter>
<filter-name>Piwik Filter</filter-name>
<filter-class>org.piwik.liferay.servlet.filter.PiwikServletFilter</filter-class>­
<init-param>
<param-name>url-regex-ignore-pattern</param-name>
<param-value>^/html/.+\.(css|gif|html|ico|jpg|js|png)(\?.*)?$</param-value>
</init-param>
</filter>

</filter-mapping>
<filter-mapping>
<filter-name>Piwik Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

And adding this one into my portla-ext.properties

# Enable the Piwik servlet filter
org.piwik.liferay.servlet.filter.PiwikServletFilter=true

# Define the URL for your piwik server
# piwik.url=http://piwik.example.com/piwik/
piwik.url=http://localhost/piwik/

# Define the site id this Liferay instance will report page hits to.
# Sites should already be defined in the piwik admin interface.
piwik.site.id=2

# Add the piwik-spring.xml to the list of xml files to load when Liferay starts
spring.configs=\
[see note],\
META-INF/piwik-spring.xml

And then i restart my server.

It gives me errors like...

SEVERE: Exception sending context initialized event to listener instance of class com.liferay.portal.spring.context.PortalContextLoaderListener
java.lang.NullPoint­erException
at com.liferay.portal.kernel.dao.orm.FinderCacheUtil.clearCache(FinderCacheUtil.jav­a:27)
at com.liferay.portal.spring.context.PortalContextLoaderListener.contextInitialized­(PortalContextLoaderListener.java:180)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779­)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273­)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
­at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:8­86)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
­at java.lang.Thread.run(Thread.java:619)
26 Jun, 2013 12:55:44 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
26 Jun, 2013 12:55:55 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [] startup failed due to previous errors
12:55:55,714 ERROR [pool-2-thread-1][PortalContextLoaderListener:107] java.lang.NullPointerException
java.lang.NullPointerException
at com.liferay.portal.kernel.servlet.DirectServletRegistryUtil.clearServlets(Direct­ServletRegistryUtil.java:27)
at com.liferay.portal.spring.context.PortalContextLoaderListener.contextDestroyed(P­ortalContextLoaderListener.java:104)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4819)­
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5466)­
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
­at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:8­86)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
­at java.lang.Thread.run(Thread.java:619)
12:55:55,718 ERROR [pool-2-thread-1][PortalContextLoaderListener:114] java.lang.NullPointerException
java.lang.NullPointerException
at com.liferay.portal.kernel.deploy.hot.HotDeployUtil.reset(HotDeployUtil.java:45)
­at com.liferay.portal.spring.context.PortalContextLoaderListener.contextDestroyed(P­ortalContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4819)­
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5466)­
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
­at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:8­86)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
­at java.lang.Thread.run(Thread.java:619)


==>>> Please Help me.

Regards..
Pradip
在 13-6-26 上午5:59 发帖以回复 David H Nebinger
Hi, I can notice a typo in your portal-ext.properties:
spring.configs=\
[see note],\
META-INF/piwik-spring.xml

Ty to remove or comment out the line:
[see note],\

and read the note, then add what is mentioned in the note to override Liferay portal.properties in your portal-ext.properties.
在 13-6-26 上午7:39 发帖。
Hi, I can notice a typo in your portal-ext.properties:
spring.configs=\
[see note],\
META-INF/piwik-spring.xml

Ty to remove or comment out the line:
[see note],\

and read the note, then add what is mentioned in the note to override Liferay portal.properties in your portal-ext.properties.
在 13-6-26 上午7:40 发帖。
Hi, Did you find the solution ?, Please share
在 13-8-6 下午11:22 发帖以回复 Pradip A Bhatt
Hi, David
I have done all stuff described above. But when I load a Liferay Portal's main page an exception is occurs. Can you help me with this issue, please?
06:58:11,895 ERROR [http-bio-8088-exec-6][PiwikServletFilter:81] java.lang.UnsupportedOperationException: Please implement processFilter(HttpServletRequest, HttpServletResponse, FilterChain)
java.lang.UnsupportedOperationException: Please implement processFilter(HttpServletRequest, HttpServletResponse, FilterChain)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:192)
­at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilt­erChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.­java:210)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:72)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
­at com.liferay.portal.servlet.filters.gzip.GZipFilter.processFilter(GZipFilter.java­:123)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFi­lter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
­at com.liferay.portal.servlet.filters.etag.ETagFilter.processFilter(ETagFilter.java­:56)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFi­lter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
­at com.liferay.portal.servlet.filters.header.HeaderFilter.processFilter(HeaderFilte­r.java:150)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFi­lter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
­at com.liferay.portal.servlet.filters.sso.ntlm.NtlmPostFilter.processFilter(NtlmPos­tFilter.java:83)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFi­lter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDire­ctCallFilter(InvokerFilterChain.java:167)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDire­ctCallFilter(InvokerFilterChain.java:167)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDire­ctCallFilter(InvokerFilterChain.java:187)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(Invoker­Filter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilt­erChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.­java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:2­25)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:1­69)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.jav­a:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at­ org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118­)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor­.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractPro­tocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)­
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:8­86)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
­at java.lang.Thread.run(Thread.java:619)
在 13-8-21 上午2:54 发帖。
I am using a Liferay Community Edition 6.1.1 CE GA2.
在 13-8-21 上午2:56 发帖。
@Bolat Kazybayev for Liferay 6.1.1 CE GA2 make the filter entry in liferay-web.xml
在 13-10-30 上午3:15 发帖。
Hi friends,
I am trying to integrate Piwik Web analytics with liferay 6.1 CE GA2 with the help of documentation in the link below:
Piwik Integration

I have made the necessary changes in ROOT/WEB-INF/web.xml and Portal-ext.properties and paste liferay-piwik 1.1 jar in tomcat/lib/ext folder.
After that when I am trying to run my server it gives an error:

 111:12:55,074 ERROR [pool-2-thread-1][ContextLoader:227] Context initialization failed
 2org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.piwik.liferay.PiwikServerConnector' defined in class path resource [META-INF/piwik-spring.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
 3    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.ini­tializeBean(AbstractAutowireCapableBeanFactory.java:1422)
 4    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doC­reateBean(AbstractAutowireCapableBeanFactory.java:518)
 5    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.cre­ateBean(AbstractAutowireCapableBeanFactory.java:455)
 6    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(Abstra­ctBeanFactory.java:293)
 7    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingle­ton(DefaultSingletonBeanRegistry.java:222)
 8    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(Abstract­BeanFactory.java:290)
 9    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBe­anFactory.java:192)
10    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstanti­ateSingletons(DefaultListableBeanFactory.java:585)
11    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactory­Initialization(AbstractApplicationContext.java:895)
12    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractA­pplicationContext.java:425)
13    at org.springframework.web.context.ContextLoader.createWebApplicationContext(Contex­tLoader.java:282)
14    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextL­oader.java:204)
15    at org.springframework.web.context.ContextLoaderListener.contextInitialized(Context­LoaderListener.java:47)
16    at com.liferay.portal.spring.context.PortalContextLoaderListener.contextInitialized­(PortalContextLoaderListener.java:172)
17    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779­)
18    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273­)
19    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
20    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
2­1    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
22    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
23    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
24    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
25    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
26    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
27    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
28    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
2­9    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
3­0    at java.lang.Thread.run(Thread.java:722)
31Caused by: java.lang.NullPointerException
32    at com.liferay.portal.util.PropsUtil._get(PropsUtil.java:209)
33    at com.liferay.portal.util.PropsUtil.get(PropsUtil.java:58)
34    at org.piwik.liferay.impl.PiwikServerConnectorImpl.afterPropertiesSet(PiwikServerCo­nnectorImpl.java:40)
35    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
36    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
37 ­   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav­a:43)
38    at java.lang.reflect.Method.invoke(Method.java:601)
39    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.inv­okeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1546)
40    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.inv­okeInitMethods(AbstractAutowireCapableBeanFactory.java:1487)
41    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.ini­tializeBean(AbstractAutowireCapableBeanFactory.java:1419)
42    ... 27 more
4311:12:55,159 ERROR [pool-2-thread-1][PortalContextLoaderListener:107] java.lang.NullPointerException
44java.lang.NullPointerException
45    at com.liferay.portal.kernel.servlet.DirectServletRegistryUtil.clearServlets(Direct­ServletRegistryUtil.java:27)
46    at com.liferay.portal.spring.context.PortalContextLoaderListener.contextDestroyed(P­ortalContextLoaderListener.java:104)
47    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4819)­
48    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5466)­
49    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
50    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
51    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
5­2    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
53    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
54    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
55    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
56    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
57    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
58    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
59    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
6­0    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
6­1    at java.lang.Thread.run(Thread.java:722)
6211:12:55,161 ERROR [pool-2-thread-1][PortalContextLoaderListener:114] java.lang.NullPointerException
63java.lang.NullPointerException
64    at com.liferay.portal.kernel.deploy.hot.HotDeployUtil.reset(HotDeployUtil.java:45)
6­5    at com.liferay.portal.spring.context.PortalContextLoaderListener.contextDestroyed(P­ortalContextLoaderListener.java:111)
66    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4819)­
67    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5466)­
68    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
69    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
70    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
7­1    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
72    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
73    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
74    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1585­)
75    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
76    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
77    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
78    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
7­9    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
8­0    at java.lang.Thread.run(Thread.java:722)


Can anyone help?

Thanks,
Surodip
在 13-12-3 上午2:25 发帖。
Hi Ankit,
I am also getting the same exception. Can you tell me the code snippet that i should paste in the liferay-web.xml..??

It will be of great help.
在 14-8-25 上午6:41 发帖以回复 tinu c p