<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <title>Terry Mueller</title>
  <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/rss" />
  <subtitle>Terry Mueller</subtitle>
  <entry>
    <title>How to use the Liferay transaction manager with Spring MVC portlets</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-the-liferay-transaction-manager-with-spring-mvc-portlets" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-the-liferay-transaction-manager-with-spring-mvc-portlets</id>
    <updated>2012-03-07T09:30:47Z</updated>
    <published>2012-03-07T09:24:05Z</published>
    <summary type="html">&lt;p&gt;Liferay provides a class-loader-proxy (CLP) for their Transaction Manager.&lt;/p&gt;&lt;p&gt;1. Add the following to your spring context.xml:&amp;nbsp;&lt;/p&gt; &lt;pre&gt;
&amp;lt;context:component-scan base-package=&amp;quot;foo.bar&amp;quot; /&amp;gt;
&amp;lt;bean id=&amp;quot;txManager&amp;quot;
  class=&amp;quot;com.liferay.util.spring.transaction.TransactionManagerClp&amp;quot;&amp;gt;
&amp;lt;/bean&amp;gt;
&amp;lt;tx:annotation-driven transaction-manager=&amp;quot;txManager&amp;quot; /&amp;gt;&lt;/pre&gt; &lt;div&gt;&lt;font face="'Courier New', Courier, monospace"&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;&lt;/font&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;2. Add the following Spring annotations to your controller methods:&lt;/p&gt; &lt;pre&gt;
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;context:component-scan base-package="foo.bar"&gt;&lt;tx:annotation-driven transaction-manager="txManager"&gt;   3. Add the following log4j to your portal-log4j-ext.xml (or log4j.properties) to see that the correct tx/session handling is being performed - once per request not once per service invocation.&lt;/tx:annotation-driven&gt;&lt;/context:component-scan&gt;&lt;/p&gt; &lt;pre&gt;
&amp;lt;category name=&amp;quot;org.springframework&amp;quot;&amp;gt;
  &amp;lt;priority value=&amp;quot;INFO&amp;quot; /&amp;gt;
&amp;lt;/category&amp;gt;&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2012-03-07T09:24:05Z</dc:date>
  </entry>
  <entry>
    <title>How to log portlet performance with Liferay</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-log-portlet-performance-with-liferay" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-log-portlet-performance-with-liferay</id>
    <updated>2011-11-22T23:28:02Z</updated>
    <published>2011-11-18T05:04:40Z</published>
    <summary type="html">&lt;p&gt;I'm currently helping a client to ensure their Liferay Portal meets the performance targets set by the business. Since many of the portlets are custom-developed, we need to identify which portlets are causing high latencies under load.&lt;/p&gt; &lt;p&gt;Set the following logger in your Log4j configuration, in our case, &lt;code&gt;tomcat/lib/META-INF/portal-log4j-ext.xml&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;lt;category name=&amp;quot;com.liferay.portlet.InvokerPortletImpl&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;priority value=&amp;quot;DEBUG&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/category&amp;gt;&lt;/p&gt;
&lt;/pre&gt; &lt;p&gt;This will cause the performance of each portlet render to be logged, for example:&amp;nbsp;&lt;/p&gt; &lt;ul&gt;     &lt;li&gt;&lt;code&gt;render for welcomeportlet_WAR_welcomeportlet takes 1 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for employmentportlet_WAR_linksportlet takes 80 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;Create instance cache wrapper for schoolbizportlet_WAR_schoolbizportlet_INSTANCE_BcM7&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for schoolbizportlet_WAR_schoolbizportlet_INSTANCE_BcM7 takes 1 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for staffsearchportlet_WAR_staffsearchportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for welcomeportlet_WAR_welcomeportlet takes 4 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for myessentialsportlet_WAR_myessentialsportlet takes 271 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for linksapplicationsportlet_WAR_linksportlet takes &lt;strong&gt;724&lt;/strong&gt; ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for myessentialsportlet_WAR_myessentialsportlet takes &lt;strong&gt;795&lt;/strong&gt; ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;render for myessentialsportlet_WAR_myessentialsportlet takes 41 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 ms&lt;/code&gt;&lt;/li&gt;     &lt;li&gt;&lt;code&gt;serveResource for latestnewsportlet_WAR_latestnewsportlet takes 2 m&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;In this example, two of the portlets stands out as taking a lot more time (700ms+) than the others.&amp;nbsp;&lt;/p&gt; &lt;p&gt;The attached PERL script &lt;a href="http://www.permeance.com.au/documents/10553/391715/calc_percentile.pl"&gt;calc_percentiles.pl&lt;/a&gt; will read a liferay log and generate a simple report on portlet performance.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;cat liferay*.log | perl calc_percentiles.pl&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Example output:&lt;/strong&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt; Portlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; N &amp;nbsp; &amp;nbsp; p0 &amp;nbsp; &amp;nbsp;p50 &amp;nbsp; &amp;nbsp;p80 &amp;nbsp; &amp;nbsp;p90 &amp;nbsp; &amp;nbsp;p99 &amp;nbsp; p100&lt;br /&gt; aupportlet_WAR_aupportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5565 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;2 &amp;nbsp; &amp;nbsp;677&lt;br /&gt; contentmarketportlet_WAR_contentmarketportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11743 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;4 &amp;nbsp; &amp;nbsp;255&lt;br /&gt; employmentportlet_WAR_linksportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;11742 &amp;nbsp; &amp;nbsp; 18 &amp;nbsp; &amp;nbsp; 99 &amp;nbsp; &amp;nbsp;128 &amp;nbsp; &amp;nbsp;168 &amp;nbsp; &amp;nbsp;383 &amp;nbsp; 1686&lt;br /&gt; errorportlet_WAR_errorportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 5 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0&lt;br /&gt; latestnewsportlet_WAR_latestnewsportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11742 &amp;nbsp; &amp;nbsp; &amp;nbsp;7 &amp;nbsp; &amp;nbsp; 11 &amp;nbsp; &amp;nbsp; 13 &amp;nbsp; &amp;nbsp; 14 &amp;nbsp; &amp;nbsp;102 &amp;nbsp; &amp;nbsp;746&lt;br /&gt; linksapplicationsportlet_WAR_linksportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1281 &amp;nbsp; &amp;nbsp; 30 &amp;nbsp; 1216 &amp;nbsp; 1945 &amp;nbsp; 2693 &amp;nbsp; 3976 &amp;nbsp;10128&lt;br /&gt; &lt;/code&gt;&lt;code&gt;linksdepartmentresourcesportlet_WAR_linksportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;386 &amp;nbsp; &amp;nbsp; 19 &amp;nbsp; &amp;nbsp; 50 &amp;nbsp; &amp;nbsp; 71 &amp;nbsp; &amp;nbsp; 90 &amp;nbsp; &amp;nbsp;349 &amp;nbsp; &amp;nbsp;406&lt;br /&gt; mybookmarksportlet_WAR_myfavouritesportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1036 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0&lt;br /&gt; mydetailsportlet_WAR_mydetailsportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 842 &amp;nbsp; &amp;nbsp; 48 &amp;nbsp; &amp;nbsp;141 &amp;nbsp; &amp;nbsp;150 &amp;nbsp; &amp;nbsp;159 &amp;nbsp; &amp;nbsp;251 &amp;nbsp; 1303&lt;br /&gt; myessentialsportlet_WAR_myessentialsportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 13874 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp;641 &amp;nbsp; 1247 &amp;nbsp; 1639 &amp;nbsp; 3090 &amp;nbsp; 8518&lt;br /&gt; myfilesportlet_WAR_myfavouritesportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;628 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;4 &amp;nbsp; &amp;nbsp; &amp;nbsp;6 &amp;nbsp; &amp;nbsp; &amp;nbsp;9 &amp;nbsp; &amp;nbsp; 24 &amp;nbsp; &amp;nbsp;207&lt;br /&gt; notificationsportlet_WAR_notificationsportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11743 &amp;nbsp; &amp;nbsp; &amp;nbsp;2 &amp;nbsp; &amp;nbsp; &amp;nbsp;4 &amp;nbsp; &amp;nbsp; &amp;nbsp;5 &amp;nbsp; &amp;nbsp; &amp;nbsp;6 &amp;nbsp; &amp;nbsp; 18 &amp;nbsp; 1584&lt;br /&gt; schoolbizportlet_WAR_schoolbizportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11742 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0&lt;br /&gt; staffsearchportlet_WAR_staffsearchportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11742 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;2 &amp;nbsp; &amp;nbsp; &amp;nbsp;2 &amp;nbsp; &amp;nbsp; &amp;nbsp;2 &amp;nbsp; &amp;nbsp; &amp;nbsp;3 &amp;nbsp; &amp;nbsp;422&lt;br /&gt; welcomeportlet_WAR_welcomeportlet &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 13057 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;1 &amp;nbsp; &amp;nbsp; &amp;nbsp;7 &amp;nbsp; &amp;nbsp; &amp;nbsp;9 &amp;nbsp; &amp;nbsp; 34 &amp;nbsp; &amp;nbsp;290&lt;/code&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-11-18T05:04:40Z</dc:date>
  </entry>
  <entry>
    <title>How to run the unit tests for Liferay Portal trunk</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-run-the-unit-tests-for-liferay-portal-trunk" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-run-the-unit-tests-for-liferay-portal-trunk</id>
    <updated>2011-11-11T05:39:09Z</updated>
    <published>2011-11-10T08:48:36Z</published>
    <summary type="html">&lt;p&gt;Running the unit tests for Liferay Portal with MacOS X is straight-forward once you know how.&lt;/p&gt; &lt;h2&gt;Set up the environment&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Install Ant 1.7+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Install MySQL 5.0+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Install Java 6.0+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Set environment variables:&lt;/p&gt;     &lt;pre&gt;
export JAVA_OPTS=&amp;quot;-Xmx512m -XX:MaxPermSize=256m&amp;quot;
export COMPUTERNAME=$HOSTNAME&amp;nbsp;&lt;/pre&gt;&lt;/li&gt; &lt;/ol&gt; &lt;h2&gt;Create the directory structure&lt;/h2&gt; &lt;p&gt;The following commands:&lt;/p&gt; &lt;pre style="margin-left: 40px; "&gt;
mkdir liferay-trunk
cd liferay-trunk
svn co http://svn.liferay.com/repos/public/portal/trunk/ src
svn co http://svn.liferay.com/repos/public/plugins/trunk/ plugins&lt;br type="_moz" /&gt;&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;will create the directory structure:&lt;/p&gt; &lt;pre style="margin-left: 40px; "&gt;
liferay-trunk/
    src/
    plugins/
&lt;br type="_moz" /&gt;&lt;/pre&gt; &lt;h2&gt;Set up the MySQL database for testing&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Install/start MySQL 5.x (in my case, 5.5.14)&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;&lt;code&gt;mysql -u root&lt;/code&gt;&amp;nbsp;and run the following to create an empty database called &lt;code&gt;lportal_trunk&lt;/code&gt;:&lt;/p&gt;     &lt;pre&gt;
create database lportal_trunk character set utf8;
grant all on lportal_trunk.* to ''@'localhost';
&lt;/pre&gt;     &lt;i&gt;&lt;br /&gt;     (so username/password not required)&lt;br /&gt;     &lt;br /&gt;     &lt;/i&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Create an empty legacy ZIP (&lt;i&gt;not sure what this was intended for but it is needed)&lt;/i&gt;:&lt;/p&gt;     &lt;pre&gt;
cd liferay-trunk/src
cd sql
mkdir legacy
zip -r legacy.zip legacy
cd ..
echo &amp;quot;sql.legacy.zip=sql/legacy.zip&amp;quot; &amp;gt; test.$COMPUTERNAME.properties
&lt;/pre&gt;     &lt;i&gt;&lt;br /&gt;     Note: test.&amp;lt;username&amp;gt;.properties gets overridden each run!&lt;br /&gt;     &lt;br /&gt;     &lt;/i&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Create&amp;nbsp;&lt;code&gt;test.$COMPUTERNAME.properties&lt;/code&gt;&amp;nbsp;as follows:&lt;/p&gt;     &lt;pre&gt;
minimal.suffix=
db.mysql.schema=lportal_trunk
mysql.executable=/usr/bin/mysql
mysql.arg.line=-u root -e &amp;quot;source create${minimal.suffix}/create${minimal.suffix}-mysql.sql&amp;quot;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;Create&amp;nbsp;&lt;code style="font-style: normal; font-weight: normal; font-family: 'Courier New', Courier, monospace; white-space: pre; "&gt;release.$COMPUTERNAME.properties&lt;/code&gt;&amp;nbsp;as follows:&lt;/p&gt;     &lt;pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;
lp.plugins.dir=${project.dir}/../plugins/build

&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;The build environment is hard-coded for Windows, so create a dummy script called &lt;code&gt;cmd.exe&lt;/code&gt; and it to your &lt;code&gt;PATH&lt;/code&gt;:&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
#!/bin/sh&lt;br /&gt;echo $*

&lt;br type="_moz" /&gt;&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;Edit &lt;code&gt;./tools/db-upgrade/portal-ext.properties&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;./portal-impl/test/portal-test.properties&lt;/code&gt; and change the database to &lt;code&gt;lportal_trunk&lt;/code&gt;:&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
jdbc.default.url=jdbc:mysql://localhost/&lt;strong&gt;lportal_trunk&lt;/strong&gt;?useUnicode=true&amp;amp;characterEncoding=UTF-8&amp;amp;useFastDateParsing=false
&lt;br type="_moz" /&gt;&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;Enable the plugins script to be executed:&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
chmod +x plugins/ext/create.sh&lt;/pre&gt;&lt;/li&gt; &lt;/ol&gt; &lt;h2&gt;Run the unit tests&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Run the tests:&lt;/p&gt;     &lt;pre&gt;
cd liferay-trunk/src
ant -buildfile build-dist.xml unzip-tomcat
cd ../plugins
ln -s ../bundles
cd ../src
ant tests
&lt;br type="_moz" /&gt;&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Review output for errors, for example:&lt;br /&gt;     &lt;i&gt;(there does not appear to be any simple way to create an HTML report)&lt;/i&gt;&lt;/p&gt;     &lt;pre&gt;
[terry@localhost portal]$ find . -name test-results -exec grep -r errors {} \; | cut -d&amp;quot; &amp;quot; -f2,3,5,6
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.MessageBusManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.ValidatorTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.DestinationManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceMonthlyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.IteratorDispatcherDestinationTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.ArrayDispatcherDestinationTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceDailyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceWeeklyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceYearlyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.DestinationStatisticsManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.UnicodePropertiesTest&amp;quot; tests=&amp;quot;2&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.StringUtilTest&amp;quot; tests=&amp;quot;3&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.util.VersionTest&amp;quot; tests=&amp;quot;5&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.service.ServiceTestSuite&amp;quot; tests=&amp;quot;24&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.util.MiscTestSuite&amp;quot; tests=&amp;quot;5&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.service.persistence.PersistenceTestSuite&amp;quot; tests=&amp;quot;880&amp;quot;


&lt;/pre&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-11-10T08:48:36Z</dc:date>
  </entry>
  <entry>
    <title>Script to delete Liferay users</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/script-to-delete-liferay-users" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/script-to-delete-liferay-users</id>
    <updated>2011-12-19T23:44:37Z</updated>
    <published>2011-11-10T02:43:17Z</published>
    <summary type="html">&lt;p&gt;The following &lt;a target="_blank" href="http://www.beanshell.org/manual/contents.html"&gt;BeanShell&lt;/a&gt; script can be used to bulk delete all non-admin users in a Liferay instance, including their groups, subscriptions, announcements, assets, blogs, &lt;em&gt;etc.&lt;/em&gt;:&lt;/p&gt; &lt;pre&gt;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import java.util.concurrent.*;

pool = Executors.newFixedThreadPool(20);

for (user : UserLocalServiceUtil.getUsers(0, 99999)) {
  if (user.isDefaultUser() || PortalUtil.isOmniadmin(user.getUserId())) {
    System.out.println(&amp;quot;Skipping user &amp;quot; + user.getScreenName());
  } else {
    final Object userToDelete = user;
    pool.execute(new Runnable() {
        public void run() {
            System.out.println(&amp;quot;Deleting user &amp;quot; + userToDelete.getScreenName());
            UserLocalServiceUtil.deleteUser(userToDelete);
        }
    });        
  }
}
&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Paste this script into &lt;em&gt;Control Panel &amp;gt; Server Administration &amp;gt; Scripts&lt;/em&gt;, with the &amp;quot;BeanShell&amp;quot; selected as the language.&lt;/p&gt; &lt;p&gt;Check the logs for the progress and/or errors.&lt;/p&gt;&lt;div class="portlet-msg-error"&gt;Note: Use with caution! This script cannot be rolled back.&lt;/div&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-11-10T02:43:17Z</dc:date>
  </entry>
  <entry>
    <title>Improved JTop with CPU per interval</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/improved-jtop-with-cpu-per-interval" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/improved-jtop-with-cpu-per-interval</id>
    <updated>2011-11-08T04:57:43Z</updated>
    <published>2011-11-08T04:45:12Z</published>
    <summary type="html">&lt;p&gt;The JTop plugin for jconsole provides information on the most resource-intensive Java threads.&lt;/p&gt;&lt;p&gt;&lt;a href="http://rejeev.blogspot.com/2009/04/thread-wise-cpu-monitoring-for-java.html"&gt;Rejeev Divakaran has extended JTop&lt;/a&gt; to include CPU &lt;em&gt;per interval&lt;/em&gt; instead of just the cumulative CPU. This makes JTop more useful for diagnosing transient spikes in CPU usage.&lt;/p&gt;&lt;p&gt;&lt;img width="600" height="245" alt="" src="http://www.permeance.com.au/image/image_gallery?uuid=94495d6a-bc26-44f1-bf77-900e960419f9&amp;amp;groupId=10553&amp;amp;t=1320728211286" /&gt;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-11-08T04:45:12Z</dc:date>
  </entry>
  <entry>
    <title>Do I have a Hibernate session leak in my Liferay portlets?</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/do-i-have-a-hibernate-session-leak-in-my-liferay-portlets-" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/do-i-have-a-hibernate-session-leak-in-my-liferay-portlets-</id>
    <updated>2011-11-01T04:48:30Z</updated>
    <published>2011-11-01T04:32:28Z</published>
    <summary type="html">&lt;p&gt;Whilst diagnosing a performance problem and memory leak, I turned on the following logging for Liferay Portal 6.0 EE SP1 to get a better view of Hibernate:&lt;/p&gt; &lt;pre&gt;
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.jdbc=DEBUG
log4j.logger.org.hibernate.transaction=DEBUG&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;I started seeing this line which made me wonder if sessions were being leaked:&lt;/p&gt; &lt;pre&gt;
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In the end, I enabled the following logging of Hibernate sessions - specifically to see the opening and closing of sessions:&amp;nbsp;&amp;nbsp;&lt;/p&gt;  &lt;pre&gt;
log4j.logger.org.hibernate.impl.SessionImpl=TRACE
&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;It turns out the above message is just a debug warning so it's nothing to worry about. The number of closes equals the number of opens:&lt;/p&gt; &lt;pre&gt;
[DEBUG] [http-9280-211] org.hibernate.impl.SessionImpl - opened session at timestamp: 5407217215401990
[TRACE] [http-9280-211] org.hibernate.impl.SessionImpl - setting flush mode to: MANUAL
[DEBUG] [http-9280-211] org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 20)
[DEBUG] [http-9280-211] org.hibernate.jdbc.ConnectionManager - opening JDBC connection
[DEBUG] [http-9280-211] org.hibernate.SQL - select resourcepe0_.resourcePermissionId as resource1_38_, resourcepe0_.companyId as companyId38_, 
resourcepe0_.name as name38_, resourcepe0_.scope as scope38_, resourcepe0_.primKey as primKey38_, resourcepe0_.roleId as roleId38_, resourcepe0_.actionIds as actionIds38_ from 
ResourcePermission resourcepe0_ where (resourcepe0_.companyId=? )AND(resourcepe0_.name=? )AND(resourcepe0_.scope=? )AND(resourcepe0_.primKey=? )
[DEBUG] [http-9280-211] org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 6)
[DEBUG] [http-9280-211] org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 7)
[DEBUG] [http-9280-211] org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 20)
[DEBUG] [http-9280-211] org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
[DEBUG] [http-9280-211] org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 14) (open ResultSets: 0, globally: 6)]
[TRACE] [http-9280-211] org.hibernate.impl.SessionImpl - after transaction completion
[TRACE] [http-9280-211] org.hibernate.impl.SessionImpl - closing session

&lt;br type="_moz" /&gt;&lt;/pre&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-11-01T04:32:28Z</dc:date>
  </entry>
  <entry>
    <title>Unable to open socket file: target process not responding or HotSpot VM not loaded</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/unable-to-open-socket-file:-target-process-not-responding-or-hotspot-vm-not-loaded" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/unable-to-open-socket-file:-target-process-not-responding-or-hotspot-vm-not-loaded</id>
    <updated>2011-10-31T07:24:39Z</updated>
    <published>2011-10-31T06:48:09Z</published>
    <summary type="html">&lt;div&gt;&lt;div&gt;When running Liferay Portal 6.0 EE SP1 + Tomcat 6.0.29, I found it impossible to take a heap dump to diagnose a memory leak.&amp;nbsp;Firstly, &lt;code&gt;&lt;a href="http://download.oracle.com/javase/6/docs/technotes/tools/share/jps.html"&gt;jps&lt;/a&gt;&lt;/code&gt; wouldn't even list the process ID so I had to use &lt;code&gt;ps&lt;/code&gt; instead:&lt;/div&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;pre&gt;
$ jps
9745 Jps&lt;/pre&gt;&lt;/div&gt; &lt;pre&gt;
&amp;nbsp;&lt;/pre&gt; &lt;div&gt;&lt;div&gt;Secondly, when creating the dump with &lt;code&gt;&lt;a href="http://download.oracle.com/javase/6/docs/technotes/tools/share/jmap.html"&gt;jmap&lt;/a&gt;&lt;/code&gt; I always got the following error:&lt;/div&gt;&lt;/div&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;pre&gt;
$ jmap -dump:file=dump.hprof 7642
7642: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding&lt;/pre&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;div&gt;The fix turned out to be somewhat unexpected. I simply had to remove the explicit declaration of the &lt;code&gt;java.io.tmpdir&lt;/code&gt; system property from our Tomcat start-up script, &lt;em&gt;i.e.&lt;/em&gt;:&lt;/div&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;div&gt;&lt;pre&gt;
-Djava.io.tmpdir=%CATALINA_BASE%/temp&lt;/pre&gt;&lt;/div&gt; &lt;pre&gt;

&lt;/pre&gt; &lt;div&gt;Now both &lt;code&gt;jps&lt;/code&gt; and &lt;code&gt;jmap&lt;/code&gt; work fine:&lt;/div&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;div&gt;&lt;pre&gt;
$ jps
4916 Jps
4068 WrapperSimpleApp&lt;/pre&gt;&lt;/div&gt; &lt;div&gt;&lt;pre&gt;

$ jmap -dump:file=dump.hprof 4068
Dumping heap to /foo/bar/dump.hprof ...
Heap dump file created&lt;/pre&gt;&lt;/div&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-10-31T06:48:09Z</dc:date>
  </entry>
  <entry>
    <title>How to determine if a user is a member of a community using the Liferay API</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-determine-if-a-user-is-a-member-of-a-community-using-the-liferay-api" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-determine-if-a-user-is-a-member-of-a-community-using-the-liferay-api</id>
    <updated>2011-10-31T05:46:31Z</updated>
    <published>2011-10-31T05:18:29Z</published>
    <summary type="html">&lt;p&gt;My client needed to determine whether a user is a member of a specific community from within a Liferay hook. The answer is very simple:&lt;/p&gt; &lt;pre&gt;
User user = ...;
Group group = GroupLocalServiceUtil.getGroup(PortalUtil.getDefaultCompanyId(), &lt;span class="s1"&gt;&amp;quot;My Community&amp;quot;&lt;/span&gt;);

if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
   // I am a member!
}&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-10-31T05:18:29Z</dc:date>
  </entry>
  <entry>
    <title>How to use time zones with Liferay Portal</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-time-zones-with-liferay-portal" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-time-zones-with-liferay-portal</id>
    <updated>2011-06-14T13:34:58Z</updated>
    <published>2011-06-14T11:53:55Z</published>
    <summary type="html">&lt;p&gt;&lt;a href="http://www.permeance.com.au/liferay-enterprise-portal"&gt;Liferay Portal&lt;/a&gt;'s handling of time zones isn't as straight forward as it might appear. But it is easy to configure once you know how.&lt;/p&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Inform Liferay of the time zones:&lt;/p&gt;     &lt;ul&gt;         &lt;li&gt;&lt;p&gt;Create &lt;code&gt;ROOT/WEB-INF/classes/system-ext.properties&lt;/code&gt; with the default time zone, for example:&lt;/p&gt;         &lt;pre&gt;
    user.timezone=Australia/Perth
&lt;/pre&gt;         &lt;p&gt;&lt;br /&gt;         where the value of&amp;nbsp;&lt;code&gt;user.timezone&lt;/code&gt; is a legal value supported by Java's &lt;a href="http://download.oracle.com/javase/6/docs/api/java/util/TimeZone.html"&gt;TimeZone&lt;/a&gt; class.&lt;/p&gt;&lt;/li&gt;         &lt;li&gt;&lt;p&gt;Create &lt;code&gt;ROOT/WEB-INF/classes/portal-ext.properties&lt;/code&gt; with a comma-separated list of the time zones in use, for example:&lt;/p&gt;         &lt;pre&gt;
    time.zones=Australia/Perth, Australia/Sydney, Australia/Adelaide
&lt;/pre&gt;&lt;/li&gt;     &lt;/ul&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;When Liferay starts for the &lt;b&gt;first time&lt;/b&gt;, it creates a default user for the company. This user is assigned the time zone obtained from the value of &lt;code&gt;user.timezone&lt;/code&gt;.&lt;/p&gt;     &lt;blockquote&gt;@see &lt;code&gt;&lt;a href="http://svn.liferay.com/browse/portal/trunk/portal-impl/src/com/liferay/portal/service/impl/CompanyLocalServiceImpl.java?r=HEAD"&gt;CompanyLocalServiceImpl#checkCompany(String webId, String mx, String shardName)&lt;/a&gt;&lt;/code&gt;&lt;/blockquote&gt;     &lt;p&gt;The data stored for the default user(s) can be viewed using:&lt;/p&gt;     &lt;blockquote&gt;     &lt;pre&gt;
select * from User_ where default = 1&lt;/pre&gt;     &lt;/blockquote&gt;     &lt;p&gt;The default user is not visible in the Control Panel but it is possible to edit the default user's time zone using &lt;em&gt;Control Panel &amp;gt; Portal &amp;gt; Settings &amp;gt; Miscellaneous &amp;gt; Display Settings &amp;gt; Time Zone&lt;/em&gt;.&lt;/p&gt;     &lt;center&gt; &lt;a href="http://www.permeance.com.au/image/image_gallery?uuid=6374e5cc-1afb-43ec-b7b0-ae47dcd1cd25&amp;amp;groupId=10553&amp;amp;t=1308057779885"&gt;&lt;img width="30%" alt="Control Panel &amp;gt; Portal &amp;gt; Settings &amp;gt; Miscellaneous &amp;gt; Display Settings &amp;gt; Time Zone&amp;lt;" src="http://www.permeance.com.au/image/image_gallery?uuid=6374e5cc-1afb-43ec-b7b0-ae47dcd1cd25&amp;amp;groupId=10553&amp;amp;t=1308057779885" /&gt;&lt;/a&gt; &lt;/center&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Whenever a &lt;b&gt;new user&lt;/b&gt; is created, it is assigned the current time zone of the &lt;b&gt;default user&lt;/b&gt;, irrespective of the current value of the &lt;code&gt;user.timezone&lt;/code&gt; system property.&lt;/p&gt;     &lt;blockquote&gt;@see &lt;code&gt;&lt;a href="http://svn.liferay.com/browse/portal/trunk/portal-impl/src/com/liferay/portal/service/impl/UserLocalServiceImpl.java?r=HEAD"&gt;UserLocalServiceImpl#addUser()&lt;/a&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;If Liferay has been running for a while without a correct &lt;code&gt;user.timezone&lt;/code&gt; system property, it is possible to update all current (and future) time zones using:&lt;/p&gt;     &lt;blockquote&gt;     &lt;pre&gt;
update User_ set timezoneid = 'Australia/Perth'&lt;/pre&gt;     &lt;/blockquote&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-06-14T11:53:55Z</dc:date>
  </entry>
  <entry>
    <title>How to export ehcache statistics to a CSV file</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-export-ehcache-statistics-to-a-csv-file" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-export-ehcache-statistics-to-a-csv-file</id>
    <updated>2011-05-24T04:49:24Z</updated>
    <published>2011-05-24T03:22:37Z</published>
    <summary type="html">&lt;p&gt;While running load testing and tuning the cache settings for Liferay, I need to periodically export the &lt;a href="http://ehcache.org/"&gt;ehcache&lt;/a&gt; statistics to a CSV file. I had a quick look at &lt;a href="http://code.google.com/p/jmxtrans/"&gt;jmxtrans&lt;/a&gt; but in the end, I wanted to write a JMX client myself as a learning exercise.&lt;/p&gt; &lt;p&gt;Here is the code:&lt;/p&gt; &lt;pre&gt;

package au.com.permeance.ehcache;

import java.net.MalformedURLException;
import java.util.HashMap;

import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class CacheStatisticsExporter {

    private static String[] ATTRIBUTE_NAMES = new String[] { &amp;quot;AssociatedCacheName&amp;quot;, &amp;quot;CacheHits&amp;quot;, &amp;quot;CacheMisses&amp;quot;, &amp;quot;ObjectCount&amp;quot; };

    public static void main(String[] args) {
        if (args.length != 4 || !args[1].matches(&amp;quot;[0-9]+&amp;quot;)) {
            System.err.println(&amp;quot;usage: java &amp;quot; + CacheStatisticsExporter.class.getName() + &amp;quot; host port username password&amp;quot;);
            System.exit(1);
        }

        String host = args[0];
        int port = Integer.valueOf(args[1]);

        HashMap&amp;lt;String, Object&amp;gt; map = new HashMap&amp;lt;String, Object&amp;gt;();
        String[] credentials = new String[2];
        credentials[0] = args[2];
        credentials[1] = args[3];
        map.put(&amp;quot;jmx.remote.credentials&amp;quot;, credentials);

        // Output header
        for (String attributeName : ATTRIBUTE_NAMES) {
            System.out.print(attributeName);
            System.out.print(&amp;quot;,&amp;quot;);
        }
        System.out.println();

        // Output values
        try {
            JMXConnector c = JMXConnectorFactory.newJMXConnector(createConnectionURL(host, port), map);
            c.connect();
            MBeanServerConnection connection = c.getMBeanServerConnection();
            for (ObjectInstance instance : 
                connection.queryMBeans(null, new ObjectName(&amp;quot;net.sf.ehcache:type=CacheStatistics,*&amp;quot;))) {
                for (Object attrObject : connection.getAttributes(instance.getObjectName(), ATTRIBUTE_NAMES)) {
                    Attribute attr = (Attribute) attrObject;
                    System.out.print(&amp;quot;\&amp;quot;&amp;quot;);
                    System.out.print(attr.getValue());
                    System.out.print(&amp;quot;\&amp;quot;,&amp;quot;);
                }
                System.out.println();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static JMXServiceURL createConnectionURL(String host, int port) throws MalformedURLException {
        return new JMXServiceURL(&amp;quot;rmi&amp;quot;, &amp;quot;&amp;quot;, 0, &amp;quot;/jndi/rmi://&amp;quot; + host + &amp;quot;:&amp;quot; + port + &amp;quot;/jmxrmi&amp;quot;);
    }

}
&lt;/pre&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;p&gt;The code itself is pretty straight forward. The usage is:&lt;/p&gt; &lt;pre&gt;
java -classpath target/classes/ au.com.permeance.ehcache.CacheStatisticsExporter host port \
     username password &amp;gt; host-ehcache-stats-`date +%Y%m%d-%H%M`.csv&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;A fragment of sample output is:&lt;/p&gt; &lt;pre&gt;
AssociatedCacheName,CacheHits,CacheMisses,ObjectCount,
&amp;quot;com.liferay.portal.util.WebCachePool&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.com.liferay.portlet.messageboards.model.impl.MBBanImpl.List&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;1&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.EntityCache.com.liferay.portal.model.impl.LayoutImpl&amp;quot;,&amp;quot;162&amp;quot;,&amp;quot;30&amp;quot;,&amp;quot;17&amp;quot;,
&amp;quot;com.liferay.portal.service.impl.PortletLocalServiceImpl&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,
&amp;quot;com.liferay.portal.util.JavaScriptBundleUtil&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;1&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.com.liferay.portal.model.impl.PasswordPolicyImpl&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,
&amp;quot;com.liferay.portal.freemarker.LiferayCacheStorage&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.EntityCache.com.liferay.portal.model.impl.ContactImpl&amp;quot;,&amp;quot;35&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;4&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.com.liferay.portal.model.impl.PluginSettingImpl&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;2&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.com.liferay.portlet.social.model.impl.SocialActivityImpl&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.Users_Roles&amp;quot;,&amp;quot;27&amp;quot;,&amp;quot;6&amp;quot;,&amp;quot;4&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.FinderCache.com.liferay.portal.model.impl.CompanyImpl.List&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;1&amp;quot;,&amp;quot;1&amp;quot;,
&amp;quot;com.liferay.portal.kernel.webcache.WebCachePool&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,
&amp;quot;com.liferay.portal.kernel.dao.orm.EntityCache.com.liferay.portlet.expando.model.impl.ExpandoTableImpl&amp;quot;,&amp;quot;9&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;1&amp;quot;,
&amp;quot;com.liferay.portal.velocity.LiferayResourceCacheUtil&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;33&amp;quot;,&lt;/pre&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;After importing this into Calc, I could easily re-sort it identify those objects which had an unsatisfactory &lt;code&gt;CacheMisses&lt;/code&gt; value.&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2011-05-24T03:22:37Z</dc:date>
  </entry>
  <entry>
    <title>How to use CSS selectors to hide Liferay web forms on submit</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-css-selectors-to-hide-liferay-web-forms-on-submit" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-use-css-selectors-to-hide-liferay-web-forms-on-submit</id>
    <updated>2011-05-05T08:07:02Z</updated>
    <published>2010-09-14T02:35:48Z</published>
    <summary type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;div.portlet-content-container div div.portlet-msg-success + form{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; display: none;&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2010-09-14T02:35:48Z</dc:date>
  </entry>
  <entry>
    <title>How to make navigation bars and breadcrumbs accessible</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-make-navigation-bars-and-breadcrumbs-accessible" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-make-navigation-bars-and-breadcrumbs-accessible</id>
    <updated>2010-09-07T01:14:24Z</updated>
    <published>2010-09-07T01:06:30Z</published>
    <summary type="html">&lt;p&gt;Navigation bars and breadcrumbs are simply a collection of links. To make these accessible, wrap them in a &lt;code&gt;&amp;lt;map&amp;gt;&lt;/code&gt;. Normally, a &lt;code&gt;&amp;lt;map&amp;gt;&lt;/code&gt; is used for image maps but this is what is recommended by &lt;a href="http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/H50"&gt;technique H50&lt;/a&gt; of WCAG 2.0. I tested this with &lt;a href="http://www.powermapper.com/products/sortsite/"&gt;SortSite&lt;/a&gt; and our breadcrumbs now pass the accessibility tests.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt; &lt;pre&gt;
&amp;lt;map title=&amp;quot;Breadcrumbs&amp;quot;&amp;gt;
  &amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt; 
  &amp;amp;gt; &amp;lt;a href=&amp;quot;/foo&amp;quot;&amp;gt;Foo&amp;lt;/a&amp;gt; 
  &amp;amp;gt; &amp;lt;a href=&amp;quot;/bar&amp;quot;&amp;gt;Bar&amp;lt;/a&amp;gt; 
  ...
&amp;lt;/map&amp;gt;
&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In this example, the &lt;code&gt;&amp;lt;map&amp;gt;&lt;/code&gt; does not affect the rendering of the breadcrumbs.&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2010-09-07T01:06:30Z</dc:date>
  </entry>
  <entry>
    <title>How to debug Liferay email</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-debug-liferay-email" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-debug-liferay-email</id>
    <updated>2010-08-20T09:19:59Z</updated>
    <published>2010-08-20T09:17:52Z</published>
    <summary type="html">&lt;p&gt;To turn on logging of Liferay mail and JavaMail, add the following to your Log4j configuration in &lt;code&gt;webapps/ROOT/WEB-INF/class/&lt;/code&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;code&gt;META-INF/portal-log4j-ext.xml&lt;/code&gt; after the last &lt;code&gt;&amp;lt;appender&amp;gt;&lt;/code&gt; entry:&lt;/p&gt; &lt;pre&gt;
    &amp;lt;logger name=&amp;quot;com.liferay.util.mail&amp;quot;&amp;gt;
        &amp;lt;level value=&amp;quot;DEBUG&amp;quot;/&amp;gt;
    &amp;lt;/logger&amp;gt;
&lt;/pre&gt; &lt;p&gt;For setting up SMTP using gmail, add the following to &lt;code&gt;webapps/ROOT/WEB-INF/classes/&lt;/code&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;code&gt;portal-ext.properties&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;
mail.session.mail.smtp.&lt;wbr&gt;&lt;/wbr&gt;socketFactory.class=javax.net.&lt;wbr&gt;&lt;/wbr&gt;ssl.SSLSocketFactory
mail.session.mail.smtp.host=sm&lt;wbr&gt;&lt;/wbr&gt;tp.gmail.com
mail.session.mail.smtp.port=&lt;wbr&gt;&lt;/wbr&gt;465
mail.session.mail.smtp.auth=&lt;wbr&gt;&lt;/wbr&gt;true
mail.session.mail.smtp.user=&amp;lt;&lt;wbr&gt;&lt;/wbr&gt;your gmail email address&amp;gt;
mail.session.mail.smtp.&lt;wbr&gt;&lt;/wbr&gt;password=&amp;lt;your password&amp;gt;&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2010-08-20T09:17:52Z</dc:date>
  </entry>
  <entry>
    <title>Internet access on the move</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/internet-access-on-the-move" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/internet-access-on-the-move</id>
    <updated>2010-05-11T16:28:38Z</updated>
    <published>2010-05-11T02:04:20Z</published>
    <summary type="html">&lt;p&gt;Here is my speed test sitting a &lt;a href="http://www.southwestcoachlines.com.au/"&gt;SouthWest Coach Lines&lt;/a&gt; bus. Not bad!&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.speedtest.net/result/810758153.png" alt="[1.17 Mb/s Download, 0.49 Mb/s Upload, 81ms Ping]" /&gt;&lt;/p&gt;&lt;p&gt;They've just put a Telstra NextG wireless modem in a cupboard at the back of the bus. No external antenna or anything.&lt;/p&gt;&lt;p&gt;They also have a USB charging plug for every seat but it does nothing for my iPhone.&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2010-05-11T02:04:20Z</dc:date>
  </entry>
  <entry>
    <title>Two CMIS projects at Apache?</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/two-cmis-projects-at-apache" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/two-cmis-projects-at-apache</id>
    <updated>2009-12-12T13:33:55Z</updated>
    <published>2009-12-12T13:25:10Z</published>
    <summary type="html">&lt;p&gt;A second CMIS project has been proposed as an incubator project at Apache:&lt;/p&gt; &lt;p style="margin-left: 40px;"&gt;&lt;a href="http://old.nabble.com/-PROPOSAL--OpenCMIS-incubator-for-Content-Mangement-Interoperability-Services-%28CMIS%29-td26713963.htm"&gt;[PROPOSAL] OpenCMIS incubator for Content Mangement Interoperability Services (CMIS)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This has raised a lot of interest within the existing &lt;a href="http://incubator.apache.org/chemistry/"&gt;Chemistry project&lt;/a&gt; (as shown in the subsequent discussion above) since they are also an incubator project for CMIS!&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Chemistry:&lt;/strong&gt;&lt;/p&gt; &lt;p style="margin-left: 40px;"&gt;&lt;em&gt;&amp;quot;Apache Chemistry is an effort to provide a Java (and possibly others, like JavaScript) implementation of the upcoming CMIS specification , consisting of a high-level API for developers wanting to manipulate documents, a low-level SPI close to the CMIS protocol for developers wanting to implement a client or a server, and default implementations for all of the above. Chemistry aims to cover both the AtomPub and SOAP bindings defined by the CMIS specifications.&amp;quot;  &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;OpenCMIS:&lt;/strong&gt;&lt;/p&gt; &lt;p style="margin-left: 40px;"&gt;&lt;em&gt;&amp;quot;OpenCMIS provides a Java implementation of the OASIS CMIS specification. This includes a library to connect as a consumer to a CMIS repository, and a library to provide the CMIS protocol handlers on top of an existing repository. All the protocol bindings defined by the CMIS specification will be supported...&lt;br /&gt; &lt;br /&gt; As the APIs are pretty different right now, contributing the OpenCMIS code to Chemistry will be very hard to do - but on a mid-term perspective, we will review our options to merge OpenCMIS with Chemistry...&amp;quot;&lt;/em&gt;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-12-12T13:25:10Z</dc:date>
  </entry>
  <entry>
    <title>How to install the Java Plugin on Firefox with Fedora 12 x86_64</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-install-the-java-plugin-on-firefox-with-fedora-12-x86_64" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-install-the-java-plugin-on-firefox-with-fedora-12-x86_64</id>
    <updated>2009-12-11T02:40:02Z</updated>
    <published>2009-12-11T02:28:09Z</published>
    <summary type="html">&lt;p&gt;After much frustration, I finally stumbled on the correct answer about installing Java Plugin on x86_64 on Linux: &lt;a href="http://plugindoc.mozdev.org/linux-amd64.html#java-sun"&gt;plugindoc.mozdev.org/linux-amd64.html#java-sun&lt;/a&gt;. This shows that the correct library to link is called &lt;strong&gt;libnpjp2.so&lt;/strong&gt;. I had tried &lt;em&gt;libjavaplugin_jni.so&lt;/em&gt; which seemed to be the closest match to &lt;em&gt;libjavaplugin_oji.so&lt;/em&gt; which everyone else spoke about. So, in short:&lt;/p&gt; &lt;pre&gt;
ln -s /usr/java/jdk1.6.0_16/jre/lib/amd64/libnpjp2.so ~/.mozilla/plugins/libnpjp2.so
 
&lt;/pre&gt; &lt;p&gt;Entering &lt;strong&gt;about:plugins&lt;/strong&gt; in the address bar shows it is registered:&lt;/p&gt; &lt;p&gt;&lt;img width="715" height="360" border="1" src="http://www.permeance.com.au/image/image_gallery?uuid=fe01ee6c-df0b-4c8e-b736-00f0967d05d5&amp;amp;groupId=10553&amp;amp;t=1260499118300" alt="About the java plugin" /&gt;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-12-11T02:28:09Z</dc:date>
  </entry>
  <entry>
    <title>Open source isn't perfect but it's pretty good</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/open-source-isn-t-perfect-but-it-s-pretty-good" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/open-source-isn-t-perfect-but-it-s-pretty-good</id>
    <updated>2009-12-08T02:19:23Z</updated>
    <published>2009-12-07T11:22:27Z</published>
    <summary type="html">&lt;p&gt;I've recently been working with Eclipse BPEL and Apache ODE and fairly quickly found bugs with both. These bugs were easy enough to fix if you have the inclinition to debug them. In all cases,&amp;nbsp;I was impressed that after contributing the patch to the respective bug tracking tools, it wasn't long before they were tested, reviewed and committed!&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Eclipse BPEL&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt;     &lt;li&gt;&lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=296532"&gt;Bug&amp;nbsp;296532&lt;/a&gt; - NPE when process folder contains files without a file extension = &lt;strong&gt;7 days&lt;/strong&gt;&lt;/li&gt;     &lt;li&gt;&lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=296538"&gt;        Bug&amp;nbsp;296538&lt;/a&gt; - Publish to the server does not preserve sub-directories = &lt;span style="font-weight: bold;"&gt;7 days&lt;/span&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Apache ODE&lt;br /&gt; &lt;/strong&gt;&lt;/p&gt; &lt;ul&gt;     &lt;li&gt;&lt;a href="https://issues.apache.org/jira/browse/ODE-725"&gt;ODE-725&lt;/a&gt; - Patch to add support for postgres to dao-jpa-db = &lt;strong&gt;&amp;lt;1 day &lt;/strong&gt;&lt;/li&gt;     &lt;li&gt;&lt;a href="https://issues.apache.org/jira/browse/ODE-731"&gt;ODE-731&lt;/a&gt; - ODE console doesn't work in IE6 = &lt;strong&gt;&amp;lt;1 day&lt;/strong&gt;&lt;/li&gt;     &lt;li&gt;&lt;a href="https://issues.apache.org/jira/browse/ODE-732"&gt;ODE-732&lt;/a&gt; - Patch for java.lang.ArrayIndexOutOfBoundsException = &lt;strong&gt;&amp;lt;1 day&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So if you find a bug in an open source product, please fix it and commit a patch!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-12-07T11:22:27Z</dc:date>
  </entry>
  <entry>
    <title>How to secure Apache ODE using Liferay users and groups</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-secure-apache-ode-using-liferay-users-and-groups" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-secure-apache-ode-using-liferay-users-and-groups</id>
    <updated>2009-12-04T08:07:30Z</updated>
    <published>2009-12-04T07:44:09Z</published>
    <summary type="html">&lt;p&gt;Rather than using a separate database (or file) of users and roles, we decided to re-use the security features of Liferay Portal. This follows on from &lt;a href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-secure-apache-ode"&gt;How to secure Apache ODE&lt;/a&gt; which you should read first.&lt;/p&gt; &lt;p&gt;&lt;em&gt;Note: The following steps were performed with Apache ODE 2.1 snapshot (trunk), Apache Tomcat 6.0.18, Liferay Portal CE 5.2.3 and PostgreSQL 8.4. They should work with some modifications for other configurations.&lt;/em&gt;&lt;/p&gt; &lt;ol&gt;     &lt;li&gt;Firstly, we need two database views that comply with&amp;nbsp;Tomcat's &lt;a href="http://tomcat.apache.org/tomcat-6.0-doc/realm-howto.html#DataSourceRealm"&gt;DataSourceRealm&lt;/a&gt;:&lt;br /&gt;     &lt;pre&gt;

CREATE USER tomcat PASSWORD 'tomcat';
CREATE SCHEMA tomcat AUTHORIZATION tomcat;

GRANT USAGE ON SCHEMA lportal TO tomcat;     
GRANT REFERENCES ON TABLE lportal.user_, lportal.users_usergroups, lportal.usergroup TO tomcat; 
GRANT SELECT ON TABLE lportal.user_, lportal.users_usergroups, lportal.usergroup TO tomcat; 

CREATE VIEW tomcat.users AS
    SELECT screenname as user_name, password_ as user_pass FROM lportal.user_;

CREATE VIEW tomcat.user_roles AS
    SELECT u.screenname AS user_name, ug.name AS role_name
    FROM lportal.user_ u, lportal.users_usergroups uug, lportal.usergroup ug
    WHERE u.userid = uug.userid AND uug.usergroupid = ug.usergroupid;

ALTER TABLE tomcat.users OWNER TO tomcat;
ALTER TABLE tomcat.user_roles OWNER TO tomcat;

&lt;/pre&gt; In this example for PostgreSQL, the Liferay tables are stored in the &lt;code&gt;lportal&lt;/code&gt; schema and the new tomcat views are created in the &lt;code&gt;tomcat&lt;/code&gt; schema. A user called &lt;code&gt;tomcat&lt;/code&gt; is created to own these views.&lt;/li&gt;     &lt;li&gt;Next, we add the &lt;code&gt;DataSourceRealm&lt;/code&gt; to &lt;code&gt;$TOMCAT/conf/server.xml&lt;/code&gt;, inside the &lt;code&gt;&amp;lt;GlobalNamingResources&amp;gt;&lt;/code&gt; area:&lt;br /&gt;     &lt;pre&gt;

    &amp;lt;Resource
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name=&amp;quot;jdbc/tomcat&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; auth=&amp;quot;Container&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type=&amp;quot;javax.sql.DataSource&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; maxActive=&amp;quot;10&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; maxIdle=&amp;quot;3&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; maxWait=&amp;quot;10000&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; username=&amp;quot;tomcat&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; password=&amp;quot;tomcat&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; driverClassName=&amp;quot;org.postgresql.Driver&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; url=&amp;quot;jdbc:postgresql://localhost/ncp&amp;quot; /&amp;gt;

&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;Finally, we declare the &lt;code&gt;Realm&lt;/code&gt; inside the &lt;code&gt;&amp;lt;Context&amp;gt;&lt;/code&gt;, providing the names of the tables and columns:&lt;/li&gt;     &lt;pre&gt;

    &amp;lt;Realm
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; className=&amp;quot;org.apache.catalina.realm.DataSourceRealm&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; debug=&amp;quot;99&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dataSourceName=&amp;quot;jdbc/tomcat&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; roleNameCol=&amp;quot;role_name&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; userCredCol=&amp;quot;user_pass&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; userNameCol=&amp;quot;user_name&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; userRoleTable=&amp;quot;tomcat.user_roles&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; userTable=&amp;quot;tomcat.users&amp;quot; /&amp;gt;

&lt;/pre&gt;     &lt;li&gt;In Liferay Portal, create a &lt;strong&gt;User Group&lt;/strong&gt; called &amp;quot;&lt;code&gt;ode-admin&lt;/code&gt;&amp;quot; and assign your users to this group.     &lt;p&gt;&lt;img width="740" height="300" border="1" src="http://www.permeance.com.au/image/image_gallery?uuid=50057da4-41d5-4140-b437-0dba7e6ff09c&amp;amp;groupId=10553&amp;amp;t=1259913054097" alt="" /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;Next, restart Tomcat.&lt;/li&gt;     &lt;li&gt;Open the ODE console using &lt;a href="http://localhost:8080/ode/"&gt;http://localhost:8080/ode/&lt;/a&gt;.&lt;/li&gt;     &lt;li&gt;When prompted, enter the username and password of a Liferay user in the &lt;code&gt;ode-admin&lt;/code&gt; user group.&lt;/li&gt; &lt;/ol&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-12-04T07:44:09Z</dc:date>
  </entry>
  <entry>
    <title>How to secure Apache ODE</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-secure-apache-ode" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-secure-apache-ode</id>
    <updated>2009-12-04T05:15:20Z</updated>
    <published>2009-12-04T04:57:58Z</published>
    <summary type="html">&lt;p&gt;Apache ODE does not have any security when installed out-of-the-box. It is simple to use Tomcat security to protect the ODE admin console.&lt;/p&gt; &lt;ol&gt;     &lt;li&gt;Add a user and role to &lt;code&gt;$TOMCAT_HOME/conf/tomcat-users.xml&lt;/code&gt;:&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
&amp;lt;role rolename=&amp;quot;ode-admin&amp;quot;/&amp;gt;
&amp;lt;user username=&amp;quot;admin&amp;quot; password=&amp;quot;xxxxxxxx&amp;quot; roles=&amp;quot;ode-admin&amp;quot;/&amp;gt;

&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;Declare the security constraints in &lt;code&gt;ode/WEB-INF/web.xml&lt;/code&gt;:&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
&amp;lt;web-app&amp;gt;
...
    &amp;lt;security-role&amp;gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;role-name&amp;gt;ode-admin&amp;lt;/role-name&amp;gt;
    &amp;lt;/security-role&amp;gt;

    &amp;lt;security-constraint&amp;gt;
        &amp;lt;display-name&amp;gt;Security constraint for the ODE admin console&amp;lt;/display-name&amp;gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;     &amp;lt;web-resource-collection&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;*.html&amp;lt;/url-pattern&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;/processes/InstanceManagement&amp;lt;/url-pattern&amp;gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;     &amp;lt;url-pattern&amp;gt;/processes/ProcessManagement&amp;lt;/url-pattern&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;/processes/DeploymentService&amp;lt;/url-pattern&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;/deployment/*&amp;lt;/url-pattern&amp;gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;     &amp;lt;http-method&amp;gt;GET&amp;lt;/http-method&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;http-method&amp;gt;POST&amp;lt;/http-method&amp;gt;
        &amp;lt;/web-resource-collection&amp;gt;
        &amp;lt;auth-constraint&amp;gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;role-name&amp;gt;ode-admin&amp;lt;/role-name&amp;gt;
        &amp;lt;/auth-constraint&amp;gt;
        &amp;lt;user-data-constraint&amp;gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;     &amp;lt;transport-guarantee&amp;gt;NONE&amp;lt;/transport-guarantee&amp;gt;
        &amp;lt;/user-data-constraint&amp;gt;
    &amp;lt;/security-constraint&amp;gt;

    &amp;lt;login-config&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
        &amp;lt;auth-method&amp;gt;BASIC&amp;lt;/auth-method&amp;gt;
    &amp;lt;/login-config&amp;gt;

&amp;lt;/web-app&amp;gt;

&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;Restart Tomcat.&lt;/li&gt;     &lt;li&gt;Now, when interacting with the ODE console at &lt;a href="http://localhost:8080/ode/"&gt;http://localhost:8080/ode/&lt;/a&gt;, it will prompt for a username and password.&lt;/li&gt;     &lt;li&gt;If you tail the access log, you can confirm that the SOAP admin calls are also protected. The processes themselves are not protected because we'll use WS-Security. In the following example, the remote user is &amp;quot;admin&amp;quot; if protected or &amp;quot;-&amp;quot; if not protected (see third column):&lt;br /&gt;     &lt;br /&gt;     &lt;pre&gt;
[terry@localhost logs]$ tail -f localhost_access_log.2009-12-04.txt 
127.0.0.1 - admin [04/Dec/2009:13:00:22 +0800] &amp;quot;POST /ode/processes/InstanceManagement HTTP/1.1&amp;quot; 200 731
127.0.0.1 - admin [04/Dec/2009:13:00:22 +0800] &amp;quot;POST /ode/processes/InstanceManagement HTTP/1.1&amp;quot; 200 731
127.0.0.1 - admin [04/Dec/2009:13:00:37 +0800] &amp;quot;POST /ode/processes/InstanceManagement HTTP/1.1&amp;quot; 200 731
127.0.0.1 - admin [04/Dec/2009:13:00:37 +0800] &amp;quot;POST /ode/processes/InstanceManagement HTTP/1.1&amp;quot; 200 731
127.0.0.1 - admin [04/Dec/2009:13:00:52 +0800] &amp;quot;POST /ode/processes/InstanceManagement HTTP/1.1&amp;quot; 200 731
...
127.0.0.1 - - [04/Dec/2009:13:13:23 +0800] &amp;quot;POST /ode/processes/HelloWorld HTTP/1.1&amp;quot; 200 255 -
...
&lt;/pre&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-12-04T04:57:58Z</dc:date>
  </entry>
  <entry>
    <title>How to run the unit tests of Liferay Portal 5.2.3 CE</title>
    <link rel="alternate" href="http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-run-the-unit-tests-of-liferay-portal-5-2-3-ce" />
    <author>
      <name>Terry Mueller</name>
    </author>
    <id>http://www.permeance.com.au/web/terry.mueller/home/-/blogs/how-to-run-the-unit-tests-of-liferay-portal-5-2-3-ce</id>
    <updated>2009-11-21T06:38:56Z</updated>
    <published>2009-11-20T07:44:04Z</published>
    <summary type="html">&lt;p&gt;Running the unit tests for Liferay Portal with Linux is straight-forward once you know how.&lt;/p&gt; &lt;h2&gt;Set up the environment&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Install Ant 1.7+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Install MySQL 5.1+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Install Java 6.0+&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Set environment variables:&lt;/p&gt;     &lt;pre&gt;
export JAVA_OPTS=-Xmx512m -XX:MaxPermSize=256m
export COMPUTERNAME=$HOSTNAME&lt;/pre&gt;     &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/li&gt; &lt;/ol&gt; &lt;h2&gt;Create the directory structure&lt;/h2&gt; &lt;p&gt;The following commands:&lt;/p&gt; &lt;pre style="margin-left: 40px;"&gt;
cd ~
mkdir liferay
wget http://downloads.sourceforge.net/project/lportal/Liferay%20Portal/\
5.2.3/liferay-portal-src-5.2.3.zip?use_mirror=transact
unzip liferay-portal-src-5.2.3.zip
mv liferay-portal-src-5.2.3 portal
&lt;/pre&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;will create the directory structure:&lt;/p&gt; &lt;pre style="margin-left: 40px;"&gt;
liferay/
    portal/
&lt;/pre&gt; &lt;h2&gt;Set up the MySQL database for testing&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;Install/start MySQL 5.x (in my case, 5.1.39)&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;&lt;code&gt;mysql -u root&lt;/code&gt; and run:&lt;/p&gt;     &lt;pre&gt;
create database lportal character set utf8;
grant all on lportal.* to ''@'localhost';
&lt;/pre&gt;     &lt;i&gt;&lt;br /&gt;     (so username/password not required)&lt;br /&gt;     &lt;br /&gt;     &lt;/i&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Create a legacy ZIP (&lt;i&gt;not sure what this was intended for 	but it is needed)&lt;/i&gt;:&lt;/p&gt;     &lt;pre&gt;
cd ~/liferay/portal/sql
mkdir legacy
zip -r legacy.zip legacy
cd ..
echo &amp;quot;sql.legacy.zip=sql/legacy.zip&amp;quot; &amp;gt; test.$COMPUTERNAME.properties
&lt;/pre&gt;     &lt;i&gt;&lt;br /&gt;     Note: test.&amp;lt;username&amp;gt;.properties gets overridden 		each run!&lt;br /&gt;     &lt;br /&gt;     &lt;/i&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;If using Linux, create &lt;code&gt;sql/test.$COMPUTERNAME.properties&lt;/code&gt; as 	follows:&lt;/p&gt;     &lt;pre&gt;
minimal.suffix=
mysql.executable=/usr/bin/mysql
mysql.arg.line=-u root -e &amp;quot;source create${minimal.suffix}/create${minimal.suffix}-mysql.sql&amp;quot;

&lt;/pre&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;If not using subversion &lt;b&gt;and&lt;/b&gt; Windoze, edit &lt;code&gt;build-test.xml&lt;/code&gt; and comment out all &lt;code&gt;&amp;lt;exec&amp;gt;&lt;/code&gt; of &lt;code&gt;cmd.exe&lt;/code&gt; to stop it attempting to revert files using subversion.&lt;/p&gt;&lt;/li&gt; &lt;/ol&gt; &lt;h2&gt;Run the unit tests&lt;/h2&gt; &lt;ol&gt;     &lt;li&gt;&lt;p&gt;&lt;code&gt;cd ~/liferay/portal&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;&lt;code&gt;ant test&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;&lt;p&gt;Review output for errors, for example:&lt;br /&gt;     &lt;i&gt;(there does not appear to 	be any simple way to create an HTML report)&lt;/i&gt;&lt;/p&gt;     &lt;pre&gt;
[terry@localhost portal]$ find . -name test-results -exec grep -r errors {} \; | cut -d&amp;quot; &amp;quot; -f2,3,5,6
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.MessageBusManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.ValidatorTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.DestinationManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceMonthlyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.IteratorDispatcherDestinationTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.ArrayDispatcherDestinationTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceDailyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceWeeklyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.RecurrenceYearlyTest&amp;quot; tests=&amp;quot;26&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.messaging.jmx.DestinationStatisticsManagerTest&amp;quot; tests=&amp;quot;1&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.UnicodePropertiesTest&amp;quot; tests=&amp;quot;2&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.kernel.util.StringUtilTest&amp;quot; tests=&amp;quot;3&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.util.VersionTest&amp;quot; tests=&amp;quot;5&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.service.ServiceTestSuite&amp;quot; tests=&amp;quot;24&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.util.MiscTestSuite&amp;quot; tests=&amp;quot;5&amp;quot;
errors=&amp;quot;0&amp;quot; failures=&amp;quot;0&amp;quot; name=&amp;quot;com.liferay.portal.service.persistence.PersistenceTestSuite&amp;quot; tests=&amp;quot;880&amp;quot;


&lt;/pre&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <dc:creator>Terry Mueller</dc:creator>
    <dc:date>2009-11-20T07:44:04Z</dc:date>
  </entry>
</feed>


