Liferay Screens is Pretty Neat

Company Blogs August 12, 2014 By James Min Staff

Here's a sneak peek at Liferay Screens Beta in the Xcode environment. Liferay Screens are basically mobile widgets that simplify development of mobile apps with Liferay as the backend.

More info here on GitHub

Youtube Preview

Common Pitfalls When Clustering Liferay

Company Blogs July 1, 2014 By James Min Staff

Trying to cluster Liferay? Think it's as simple as just putting a bunch of Liferay servers behind a load balancer? Think again. Here are some of the top pitfalls when setting up a clustered Liferay environment:


1. Merely copying Liferay and putting it behind a load balancer. 

Do not do this and think you are done. You must account for the local caching, indexing, and document repository storage. Did you know that, via the default configuration, each Liferay server has a local instance of all of the above? Use ClusterLink to synchronize the cache (Ehcache), and index (Lucene), and decide on a central way to mount or store documents (e.g. - SAN, NAS, Amazon S3, etc.). Failure to do this will not only cause users to see inconsistent content and behavior from node to node, but also cause data corruption for your documents because each node will only have a portion of the entire document repository, even though the document metadata is already centralized in the database. The actual documents files are stored on the local server's file system by default. Not only that, other nodes may not be aware of new or updated documents due to a stale cache and index. This is probably the most common mistake I have seen by those new to Liferay who have not taken the Administering Liferay Systems course or thoroughly read the documentaton



2. Assuming multicast works in your hosting vendor's environment

This is often not the case for the cloud. For example, did you know that Amazon Web Services does not support multicast or broadcast? See: . You must configure use a unicast configuration for your cache and index replication.



3. Not eliminating other single points of failure

Although taking care of (1) and (2) above will typically ensure data integrity and a consistent user experience, in some high-volume environments, there are elements of Liferay High Availability that need to be addressed to ensure consistent and reasonably quick response time. Configuring a database cluster (e.g. - MySQL Cluster, Oracle RAC, etc.) will eliminate outages cause by a database server going down. Installing the Solr plugin and clustering your Solr servers is one way to not only speed up heavy indexing, but clustering Solr itself also eliminates another single point of failure. Adding redundancy at the load balancer level is not necessarily a Liferay configuration, however it will eliminate another single point of failure. For the document repository, even though you may have configured a centralized document repository as recommended above, adding redundancy via SAN replication or another method will also prevent headaches if the document storage method goes down. 



For more documention on Liferay Clustering options, see the online documentation at:



Liferay + TIBCO!

Company Blogs April 30, 2013 By James Min Staff

Enterprise Portal Liferay Partners with TIBCO Software for Lower Cost Back-End Integration

6 Years!

Company Blogs August 15, 2012 By James Min Staff

6 years ago, I joined #Liferay. Longest and best job I've had, not to mention the fantastic people and product. Here's to year 7!

Liferay listed as monthly recommendation at CMSCritic

Company Blogs February 1, 2012 By James Min Staff


"Liferay:  This company has been growing like a weed over the last few years and is continuing to do so. Liferay's unique portal solutions can be adapted to almost any type of deployment required. It's a young company run by passionate young people who have been actively pushing their CMS into the enterprise space with zest. Liferay is one of the many companies that have had success blending Open Source offerings with Commercial ones and has been continuously profitable. Check out Liferay."

Liferay WCS and Jenkins User Conference

Company Blogs August 25, 2011 By James Min Staff

I'll be running a workshop at Liferay WCS on Backend Integrations in September, and also presenting at the first Jenkins User Conference (JUC) in October where Liferay is a sponsor


Liferay WCS
I ran a similar "Backend Integrations" workshop at the Liferay ECS last spring, and thanks to the feedback from attendees, we hope to have a more streamlined workshop (and set-up) for WCS. Understanding what it takes to integrate with 3rd-party systems and APIs is the goal, not to mention showing how fast and easy it is to deploy the Liferay plugins that we will develop. Register now! Check out the agenda and speakers. At WCS we will have some big announcements about Liferay's new release and the highly anticipated Liferay Marketplace


This is the first JUC and will be my first time meeting so many Jenkins users! I'm pretty excited to talk about Liferay's monster Jenkins setup. This past week, I got to talk with our CSA Brian Chan over lunch about what we're doing now and the resources we are planning to invest in our Jenkins setup in the coming months. Quite simply, it is staggering. If you saw his blog post about how Liferay uses Hudson last year, you haven't seen anything yet! Looking forward to meeting many Jenkins users and seeing the amazing things people are doing out there!


Oracle OpenWorld
Right after JUC, I'll be at the Liferay booth at Oracle OpenWorld 2011. Drop by if you'd like to talk about Liferay, or just chat and meet some Liferay folks!


We Are Not A Sausage Factory!

Company Blogs May 27, 2011 By James Min Staff

I finally got around to watching the film, Welcome To Macintosh. I thought it was hilarious, whether you are an Apple fanboy, a staunch Windows user, or Linux freak (like me). I thought this ex-Apple engineer was the funniest. He used to be with Apple pretty much from the start, and left before Apple's latest boom in the 2000's. He worked on their OS team, worked on Quicktime, and the sound manager (among other things). He also was responsible for the Mac startup sound that is still there today. 



The funniest comment he made was at about the 1:48 mark:

"The people on the outside think that, ya know... It's like this wonderful world of Oz, or Disney going on, and all of us are just these brilliant amazing happy people, and like, it's not. It's like a sausage factory, man, you really don't wanna know how this stuff happens. A lot of it is just bad arguments, politics, and working around the rules, and not doing the right thing, and apologizing for it later, and getting fired a few times. I mean, that's how things got done. It's definietly like, 'Don't pay attention to the man behind the curtain," There's a lot of that kind of stuff. And like, you really don't want to know how this stuff is built. To me, it's embarrassing, like, there's always big flaws to a lot of this stuff."

If you've had the experience of working for at least a few companies in the software industry, you probably think this is hilarious because it is often true. Even at a company like Apple, which has risen from the brink of being obsolete in the 90's, to being a company and brand that is synonymous with design and engineering (at least to the public at large), there are skeletons. 

I've worked in software development for the health care industry, a small enterprise software company during the dot com boom of the 90's, for Sun Microsystems, for an investment bank in NYC, and in the entertainment industry for one of the big studios in Los Angeles. Liferay is the first place that I have worked where I am really proud of the code! It's a pretty darn clean (albeit large) code base. Our chief software architect, Brian Chan, might disagree and say it could be even cleaner, but my personal opinion is that his OCD nature toward the portal core won't ever let him be satisfied. I can't say I haven't witnessed some heated arguments between Liferay core developers, but if you ask me, it's always resulted in what is best for the product at that time, and most importantly, best for the Liferay community... not to mention something that is just plain cool. 

Anyhow, if you haven't seen the film, I'd recommend it for some laughs, especially if you have ever worked for a hi tech company. Depending on your view of Apple,however, you may be put off by some of the Apple "propaganda". Still, I found it entertaining. wink

Just for the record, this is absolutely not an indication of how Apple currently does business. The film was simply entertaining and I do enjoy many of Apple's products, from my first Mac SE/30 to my iPhone4 today. 

Why Load Balancing != Clustering in Liferay

Company Blogs February 8, 2010 By James Min Staff

Just a quick post on a couple of misunderstandings I've seen out in the field lately... Simply setting up Liferay Portal to be load balanced does *not* mean it is clustered. 

First, let's be clear on what "load balancing" is. Load balancing is simply a technique to distribute workload across resources. It is but one component in a high-availability cluster. In Liferay's case, we are load balancing the volume of requests across multiple app servers, which may or may not be on physically separate hardware. Initially, this may seem sufficient, until you realize some of the components that the portal uses.


Clustering is not just pointing a load balancer to two (or more) Liferay nodes. You're not done. Why? Because there are certain components that need to be either centrally managed or synchronized. Here is the basic check list of components that need to be addressed in a Liferay cluster:


1. Load Balancer - it can be software (i.e. - Apache), or hardware (F5), or whatever you wish, really. All it is doing is redirecting requests. 

2. Centralized Database - Hopefully, you have gotten off of HSQL and are using a real DB server. This is a JBDC connection. It is abstracted from Liferay's point of view. Any level of redundancy you have behind that JDBC connection is up to you and your DBA. Just as an example, you may choose to configure a MySQL cluster, or Oracle RAC, for DB high availability

3. Ehcache - This is what Liferay uses out-of-the-box for it's Hibernate level 2 cache. This needs to be configured to sync, else you will see inconsistencies depending on what node the load balancer redirects end users to. You are not forced to use Ehcache, it is simply what it ships with. You could use something like Terracotta, for example. If you do not do this, you will most definitely see inconsistencies depending on the node the end user is on, due to stale caches. 

4. Lucene - This needs to be centralized. This can be done: a) via JDBC (can work, but there may be issues with speed and table locks), b) swapped out for something like SOLR (runs as a webapp in Tomcat), or c) starting with Liferay 5.2 SP1 there is a clusterlink feature that can be turned on where each node maintains its own replicated cache. If you do not do this, you will see inconsistencies with search and other indexed data that is returned from the DB. 

5. Document Library & Image Gallery - This needs to be centralized. This is because each node keeps the assets locally on the filesystem by default. While the meta-data is in the DB, the files serve up faster this way (vs. BLOBS in a DB). So, you need to either a) point the content repository to be stored in the DB (can work but performance may suffer) via JCRHook in portal properties, or b) mount a path a shared storage (i.e. SAN or other file system storage) and configure each node to connect to this common place via AdvancedFileSystemHook in portal properties. If you do not do this, the meta-data regarding your documents will be in the DB, but when you try to retrieve them, the node may or may not find the document there, physically. 


This is just an outline of what needs to be done. To find out more details consult the Liferay Portal Administrator's Guide or contact Liferay Professional Services

External Databases/Datasources

Company Blogs October 26, 2009 By James Min Staff

Probably one of the top 5 questions I get asked on consulting gigs is, "How do I connect to an external database?"

The wiki was a bit out of date, so I made a new one for Liferay 5.2.

Wiki: Connecting to an External Database and Building Services Against It

I'm sorry that it is not prettier and not more well-organized. I'll have to pretty it up later, and make it more Wiki-ish. But I just wanted to get the info out there. Also, maybe I will rewrite it to put the service layer in the actual plugin. Enjoy.

General Perfomance Tuning Principles

Company Blogs September 2, 2009 By James Min Staff

Long time no post...

I do a lot of our customer performance tuning jobs, and there are some guiding princliples that apply in every environment.

A good place to start is to have a set of portal properties, xml configurations, and JVM flags that you know that you will use and apply every time. But that can only go so far, because every app is different and has different needs.

Performance tuning is a very iterative process. It involves 3 main components:

  1. A repeatable test script
  2. A load test client
  3. A Java profiler

General Steps:

  1. The first thing you need to do is to decide what you want to do for your test. Do you simply want to hit localhost, sign in, and sign out? Or do you want to browse around many pages with certain portlets placed on each page before signing out? Find out what the customer wants and decide on a test, or a number of test cases, early on and stay consistent throughout the performance tuning process. This will ensure meaningful results.
  2. The next thing you need to do is create the script for the repeatable test. For example, in Apache JMeter, it is easy to use the built-in proxy server to record a test script, based on your click actions. You can save this and run it multiple times across multiple threads.
  3. Decide how many concurrent users and repetitions you want to run this test as. For example, if the customer wants to test 200 concurrent users, you would configure JMeter to run 200 threads. You could maybe ramp them up 3 seconds apart, so in JMeter, you would configure the 200 threads to run within 600 seconds (i.e. - every 3 seconds, a thread will be started, each thread executing the test script).
  4. Establish a baseline. This is a very important step, as this will prove that there was measurable improvement backed up by statistics. In JMeter, you can use the aggregate report to gather data for this baseline. You have to show that you started somewhere.
  5. Use a Java profiler. Why is this important? Because if you are stuck on why the CPU is spiking so much, why the memory keeps growing, why certain threads seem to be blocked... apart from some very clever debugging in the code or a lucky guess, you will need a Java profiler to really nail down what the true cause is. This is because a Java profiler can examine what is in the JVM. It can examine what objects are in memory, how much memory you have available, how much memory is allocated, CPU performance and spiking, active threads, blocked or waiting threads, and much more. Recommended profilers are JProfiler, YourKit Java Profiler, and Netbeans Profiler.
  6. Identify bottlenecks. Once you have the profiler in place, it will be much easier to see the bottlenecks. Is it too little heap? Is it processor power? Is there a memory leak? Are there blocked threads? Once you identify the bottlenecks, you can address those bottlenecks via configuration or code changes. Then deploy your changes.
  7. Repeat the above steps. You must use the same test and run it the same way, after you have addressed your bottlenecks. You will most likely run into another, different bottleneck, but that is OK. The point is that you want to keep addressing the bottlenecks as they show up, address them, repeat the process, until you get the desired performance that you want. Take measurements and record statistics after every iteration! This will show progress.

If you do not use a Java profiler, it is almost always a wild guess as to what the problem is. Maybe an educated guess, but it's still a guess. Yes there is some overhead when attaching the Java profiler to the app server, but most times, this is negligible in testing scenarios. Again, this is very much an iterative process. Test, identify bottlenecks, address bottlenecks, rinse-repeat. Usually for customers we estimate 5 days. It's not something that can be done with quality, overnight. The iterations, configuration changes, code changes, redeployments, and testing all take time.

Lastly, do not run the tests in production! Make a copy and a test environment. The tests are supposed to be designed to slow down the system to reveal and identify the bottlenecks.


Quick Web Services Tip

Company Blogs August 14, 2008 By James Min Staff

I've been being asked this a lot recently, so I'm going to blog it. Also a wiki on it.



To see a listing of available web services (v 5.1), you can go to the following URL with Liferay running locally:


It will also give you access to the WSDL files. It looks like this:

And now... Some Services

  • Portal_AccountService (wsdl)
  • Portlet_IG_IGImageService (wsdl)
    • deleteImage
    • getImages
    • getImageByFolderIdAndNameWithExtension
    • getImageByLargeImageId
    • getImageBySmallImageId
    • deleteImageByFolderIdAndNameWithExtension
    • getImage
  • Portlet_SC_SCFrameworkVersionService (wsdl)
    • addFrameworkVersion
    • addFrameworkVersion
    • deleteFrameworkVersion
    • getFrameworkVersion
    • getFrameworkVersions
    • getFrameworkVersions
    • updateFrameworkVersion
  • Portlet_Shopping_ShoppingItemService (wsdl)
    • addBookItems
    • deleteItem
    • getItem
  • Portlet_DL_DLFolderService (wsdl)
    • getFolderId
    • getFolder
    • getFolder
    • updateFolder
    • addFolder
    • addFolder
    • deleteFolder
    • deleteFolder
    • getFolders
    • copyFolder
    • reIndexSearch
  • Portlet_DL_DLFileShortcutService (wsdl)
    • addFileShortcut
    • addFileShortcut
    • deleteFileShortcut
    • getFileShortcut
    • updateFileShortcut
  • Portlet_Polls_PollsVoteService (wsdl)
    • addVote
  • Portlet_SC_SCProductEntryService (wsdl)
    • addProductEntry
    • addProductEntry
    • deleteProductEntry
    • getProductEntry
    • updateProductEntry
  • Portlet_Announcements_AnnouncementsDeliveryService (wsdl)
    • updateDelivery
  • Portlet_Workflow_WorkflowDefinitionService (wsdl)
    • getDefinition
    • addDefinition
    • addDefinition
    • addDefinition
    • addDefinitionResources
    • addDefinitionResources
  • Portlet_Shopping_ShoppingCouponService (wsdl)
    • addCoupon
    • deleteCoupon
    • getCoupon
    • updateCoupon
    • search
  • Portal_UserGroupService (wsdl)
    • getUserGroup
    • getUserGroup
    • addUserGroup
    • addGroupUserGroups
    • deleteUserGroup
    • getUserUserGroups
    • unsetGroupUserGroups
    • updateUserGroup
  • Portlet_Announcements_AnnouncementsEntryService (wsdl)
    • updateEntry
    • addEntry
    • deleteEntry
  • AdminService (wsdl)
    • AdminService
  • Version (wsdl)
    • getVersion
  • Portlet_Workflow_WorkflowInstanceService (wsdl)
    • signalInstance
    • signalToken
    • addInstance
  • Portal_WebsiteService (wsdl)
    • addWebsite
    • deleteWebsite
    • getWebsite
    • getWebsites
    • updateWebsite
  • Portlet_MB_MBCategoryService (wsdl)
    • getCategory
    • addCategory
    • addCategory
    • deleteCategory
    • getCategoriesCount
    • updateCategory
    • subscribeCategory
    • unsubscribeCategory
    • getCategories
  • Portlet_Bookmarks_BookmarksEntryService (wsdl)
    • openEntry
    • updateEntry
    • addEntry
    • addEntry
    • getEntry
    • deleteEntry
  • Portal_PermissionService (wsdl)
    • setRolePermission
    • hasGroupPermission
    • hasUserPermission
    • hasUserPermissions
    • setGroupPermissions
    • setGroupPermissions
    • setOrgGroupPermissions
    • unsetRolePermissions
    • setRolePermissions
    • setUserPermissions
    • unsetRolePermission
    • unsetRolePermission
    • unsetUserPermissions
    • checkPermission
  • Portal_MembershipRequestService (wsdl)
    • deleteMembershipRequests
    • addMembershipRequest
    • getMembershipRequest
    • updateStatus
  • Portal_EmailAddressService (wsdl)
    • deleteEmailAddress
    • updateEmailAddress
    • getEmailAddress
    • addEmailAddress
    • getEmailAddresses
  • Portal_PortletPreferencesService (wsdl)
    • deleteArchivedPreferences
  • Portal_LayoutService (wsdl)
    • addLayout
    • deleteLayout
    • deleteLayout
    • setLayouts
    • updateLookAndFeel
    • updateName
    • updateName
    • updateParentLayoutId
    • updateParentLayoutId
    • updatePriority
    • updatePriority
    • getLayoutName
    • getLayoutReferences
    • unschedulePublishToLive
    • unschedulePublishToRemote
    • updateLayout
  • Portlet_Workflow_WorkflowComponentService (wsdl)
    • getTask
    • deploy
    • getCurrentTasks
    • getCurrentTasksXml
    • getDefinition
    • getDefinitions
    • getDefinitionsXml
    • getDefinitionsCount
    • getDefinitionsCountXml
    • getDefinitionXml
    • getInstances
    • getInstancesCount
    • getInstancesCountXml
    • getInstancesXml
    • getTaskXml
    • getTaskFormElements
    • getTaskFormElementsXml
    • getTaskTransitions
    • getTaskTransitionsXml
    • getUserTasks
    • getUserTasksCount
    • getUserTasksCountXml
    • getUserTasksXml
    • signalInstance
    • signalToken
    • startWorkflow
  • Portal_PortalService (wsdl)
    • test
  • Portlet_Journal_JournalStructureService (wsdl)
    • addStructure
    • addStructure
    • deleteStructure
    • getStructure
    • updateStructure
  • Portlet_Journal_JournalArticleService (wsdl)
    • getArticle
    • removeArticleLocale
    • removeArticleLocale
    • updateContent
  • Portal_OrganizationService (wsdl)
    • getUserOrganizations
    • getOrganizationId
    • addOrganization
    • addGroupOrganizations
    • addPasswordPolicyOrganizations
    • deleteOrganization
    • setGroupOrganizations
    • unsetGroupOrganizations
    • unsetPasswordPolicyOrganizations
    • updateOrganization
    • getOrganization
  • Portal_GroupService (wsdl)
    • updateGroup
    • updateGroup
    • addGroup
    • addGroup
    • addRoleGroups
    • deleteGroup
    • getOrganizationsGroups
    • getUserGroupsGroups
    • hasUserGroup
    • searchCount
    • setRoleGroups
    • unsetRoleGroups
    • updateFriendlyURL
    • updateWorkflow
    • search
    • getGroup
    • getGroup
  • Portlet_Bookmarks_BookmarksFolderService (wsdl)
    • getFolder
    • updateFolder
    • addFolder
    • addFolder
    • deleteFolder
  • Portlet_DL_DLFileEntryService (wsdl)
    • addFileEntry
    • addFileEntry
    • deleteFileEntry
    • deleteFileEntry
    • deleteFileEntryByTitle
    • getFileEntries
    • getFileEntry
    • getFileEntryByTitle
    • lockFileEntry
    • unlockFileEntry
    • updateFileEntry
  • Portlet_Tags_TagsSourceService (wsdl)
  • Portal_ListTypeService (wsdl)
    • getListType
    • getListTypes
    • validate
    • validate
  • Portlet_Shopping_ShoppingCategoryService (wsdl)
    • getCategory
    • addCategory
    • addCategory
    • deleteCategory
    • updateCategory
  • Portlet_Cal_CalEventService (wsdl)
    • deleteEvent
    • getEvent
    • updateEvent
    • addEvent
    • addEvent
  • Portal_UserService (wsdl)
    • getUserById
    • getDefaultUserId
    • addUser
    • deleteUser
    • updatePassword
    • addGroupUsers
    • addOrganizationUsers
    • addPasswordPolicyUsers
    • addRoleUsers
    • addUserGroupUsers
    • updateOrganizations
    • getUserByEmailAddress
    • getUserByScreenName
    • deleteRoleUser
    • getGroupUsers
    • getRoleUsers
    • getUserIdByEmailAddress
    • getUserIdByScreenName
    • hasGroupUser
    • hasRoleUser
    • setRoleUsers
    • setUserGroupUsers
    • unsetGroupUsers
    • unsetOrganizationUsers
    • unsetPasswordPolicyUsers
    • unsetRoleUsers
    • unsetUserGroupUsers
    • updateActive
    • updateAgreedToTermsOfUse
    • updateLockout
    • updateOpenId
    • updatePortrait
    • updateScreenName
    • updateUser
    • updateUser
  • Portal_RoleService (wsdl)
    • getRole
    • getRole
    • hasUserRole
    • getGroupRole
    • deleteRole
    • addRole
    • addUserRoles
    • getGroupRoles
    • getUserGroupRoles
    • getUserRelatedRoles
    • getUserRoles
    • hasUserRoles
    • unsetUserRoles
    • updateRole
  • Portlet_IG_IGFolderService (wsdl)
    • addFolder
    • addFolder
    • copyFolder
    • deleteFolder
    • getFolder
    • getFolder
    • getFolders
    • updateFolder
  • Portlet_Polls_PollsQuestionService (wsdl)
    • addQuestion
    • addQuestion
    • deleteQuestion
    • getQuestion
    • updateQuestion
  • Portal_ContactService (wsdl)
  • Portal_PhoneService (wsdl)
    • addPhone
    • deletePhone
    • getPhone
    • getPhones
    • updatePhone
  • Portal_PortletService (wsdl)
    • updatePortlet
    • getWARPortlets
  • Portlet_Workflow_WorkflowTaskService (wsdl)
  • Portal_OrgLaborService (wsdl)
    • addOrgLabor
    • deleteOrgLabor
    • getOrgLabor
    • getOrgLabors
    • updateOrgLabor
  • Portal_AddressService (wsdl)
    • addAddress
    • deleteAddress
    • getAddresses
    • updateAddress
    • getAddress
  • Portal_CountryService (wsdl)
    • addCountry
    • getCountries
    • getCountries
    • getCountry
  • Portlet_Blogs_BlogsEntryService (wsdl)
    • getCompanyEntries
    • getGroupEntries
    • getOrganizationEntries
    • getEntry
    • getEntry
    • deleteEntry
  • Portal_PasswordPolicyService (wsdl)
    • addPasswordPolicy
    • deletePasswordPolicy
    • updatePasswordPolicy
  • Portlet_MB_MBBanService (wsdl)
    • addBan
    • deleteBan
  • Portlet_Shopping_ShoppingOrderService (wsdl)
    • getOrder
    • sendEmail
    • completeOrder
    • deleteOrder
    • updateOrder
    • updateOrder
  • Portal_RegionService (wsdl)
    • addRegion
    • getRegions
    • getRegions
    • getRegions
    • getRegions
    • getRegion
  • Portlet_Journal_JournalFeedService (wsdl)
    • addFeed
    • addFeed
    • deleteFeed
    • deleteFeed
    • getFeed
    • getFeed
    • updateFeed
  • Portlet_Tags_TagsPropertyService (wsdl)
    • addProperty
    • addProperty
    • getPropertyValues
    • deleteProperty
    • updateProperty
    • getProperties
  • Portlet_Ratings_RatingsEntryService (wsdl)
    • updateEntry
    • deleteEntry
  • Portlet_MB_MBMessageService (wsdl)
    • addMessage
    • addMessage
    • addMessage
    • addMessage
    • updateMessage
    • deleteDiscussionMessage
    • deleteMessage
    • getCategoryMessages
    • getCategoryMessagesCount
    • getMessageDisplay
    • subscribeMessage
    • unsubscribeMessage
    • updateDiscussionMessage
    • getMessage
  • Portlet_SC_SCProductVersionService (wsdl)
    • addProductVersion
    • addProductVersion
    • deleteProductVersion
    • getProductVersion
    • getProductVersions
    • getProductVersionsCount
    • updateProductVersion
  • Portlet_Tags_TagsEntryService (wsdl)
    • updateEntry
    • updateEntry
    • searchCount
    • mergeEntries
    • searchAutocomplete
    • addEntry
    • addEntry
    • search
    • search
    • deleteEntry
    • getEntries
    • getEntries
  • Portlet_Tasks_TasksReviewService (wsdl)
    • approveReview
    • rejectReview
    • updateReviews
  • Portal_LayoutSetService (wsdl)
    • updateLookAndFeel
    • updateVirtualHost
  • Portlet_SC_SCLicenseService (wsdl)
    • addLicense
    • deleteLicense
    • getLicense
    • updateLicense
  • Portal_ClassNameService (wsdl)
    • getClassName
    • getClassName
  • Portal_UserGroupRoleService (wsdl)
    • addUserGroupRoles
    • addUserGroupRoles
    • deleteUserGroupRoles
    • deleteUserGroupRoles
  • Portlet_Reports_ReportsEntryService (wsdl)
  • Portal_PluginSettingService (wsdl)
    • updatePluginSetting
  • Portal_ResourceService (wsdl)
    • getResource
  • Portlet_Tasks_TasksProposalService (wsdl)
    • deleteProposal
    • addProposal
    • addProposal
    • updateProposal
  • Portlet_Wiki_WikiNodeService (wsdl)
    • addNode
    • addNode
    • deleteNode
    • subscribeNode
    • unsubscribeNode
    • updateNode
    • getNode
    • getNode
  • Portlet_MB_MBThreadService (wsdl)
    • moveThread
  • Portlet_Journal_JournalTemplateService (wsdl)
    • deleteTemplate
    • getStructureTemplates
    • getTemplate
  • Portlet_Wiki_WikiPageService (wsdl)
    • addPageAttachments
    • deletePage
    • deletePageAttachment
    • subscribePage
    • unsubscribePage
    • getNodePages
    • getNodePagesRSS
    • getPagesRSS
    • getPage
    • getPage
  • Portlet_Announcements_AnnouncementsFlagService (wsdl)
    • deleteFlag
    • getFlag
    • addFlag
  • Portlet_Tags_TagsAssetService (wsdl)
    • deleteAsset
    • getAsset
    • getAssetsRSS
    • getAssetTypes
    • getCompanyAssetDisplays
    • getCompanyAssets
    • getCompanyAssetsCount
    • getCompanyAssetsRSS
    • incrementViewCounter
    • searchAssetDisplays
    • searchAssetDisplaysCount
    • updateAsset
  • Portal_CompanyService (wsdl)
    • addCompany
    • updateCompany
    • updateCompany
    • updateSecurity
    • updateDisplay


Pre 5.0

Pre-5.0, you can get a similar listing here:


How Do I Profile Liferay for Better Performance?

Company Blogs June 5, 2008 By James Min Staff

Want to tune Liferay for better performance? There are several things that you can do. There is no magic wand that turbo charges your web app. There is this wiki article which has some properties you can set:


But in the end, Liferay is a Java web application that runs in the JVM. Hence, you have to do some JVM tuning. Java profiling can be very useful in pinpointing potential problem areas and bottlenecks. We don't necessarily endorse a particular Java profiler, but I'll just give an example using YourKit. Java profiling and tuning is largely an iterative process. You profile, analyze, tune... rinse, repeat. Everyone's app is different. But in the end you want to make CPU and memory usage more efficient, resulting in faster response and performance.



1) A working Liferay installation on Tomcat
2) YourKit for the platform your app is running, on as well as the platform you want to run the profiler from.


Basic Concept:

1) You have to run Tomcat with profiling enabled.
2) You then run the profiler client and attach it to that web app. It will find it because it was started with profiling enabled.



1) Set up Tomcat to be profiled

There are excellent steps here, but here it is for your benefit:

Run the wizard:

java -jar lib/yjp.jar -integrate


That should create a script: tomcat/bin/

What is the difference you ask? Well, it is simply the file with some extra libraries, enabling it to be profiled. You run this script when you profile, not in production. Here's a diff:



It basically added:

# Generated with YourKit Java Profiler 7.5.0
# Path to proper version of profiler agent library (Linux, 32-bit JVM)
export LD_LIBRARY_PATH="$_YH_/bin/linux-x86-32:$LD_LIBRARY_PATH"
JAVA_TOOL_OPTIONS="-agentlib:yjpagent=sessionname=Tomcat $JAVA_TOOL_OPTIONS"
JAVA_OPTS="-Xrunyjpagent:sessionname=Tomcat $JAVA_OPTS"
export JAVA_OPTS


2) Let's start Tomcat with the new script.

It should output something like this in the log:

Picked up JAVA_TOOL_OPTIONS: -agentlib:yjpagent=sessionname=Tomcat 
[YourKit Java Profiler 7.5.0] Using JVMTI (10.0-b22;Sun Microsystems Inc.; mixed mode, sharing;
Linux;32 bit JVM)
[YourKit Java Profiler 7.5.0] Profiler agent is listening on port 10001...
[YourKit Java Profiler 7.5.0] *** HINT ***: To get profiling results, connect to the application
from the profiler UI
Jun 5, 2008 7:17:30 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent

3) Start up the YourKit profiler.



Click "Connect to locally running profiled application..." and it will find the Tomcat you just started! From there, it will create new tab with a profile of your app.


Take snapshots

You can see what your web app is doing live. Click "Start CPU Profiling" but uncheck "Profile J2EE" so you can focus on just Liferay.


To analyze deeper, you need to take a performance snapshot and memory snapshot.


To get a really useful snapshot, you will need to run some sort of load generator, such as JMeter. Then take the snapshots. From there you can identify "hot spots" and make tweaks from there. Again, this is an iterative process, until you get what you want.

JVM Tuning?
I can't really recommend specific JVM tuning settings, because, as I stated before, every app is different. You need to identify problem areas and address those as they come along. Needless to say, there is some JVM expertise required here. You can also hire Liferay's consulting services for a custom solution that fits your system's performance requirements. 

Anyhow, that should get you started. There is a lot of helpful info here on diagnosis:

Read up on how to troubleshoot performance problems and how to use and interpet the data in YourKit.




Liferay Builds with the ECJ Compiler

Company Blogs March 19, 2008 By James Min Staff

I just made a Wiki on how to configure ECJ for your Liferay builds. It is here, but I'll just paste the most important parts:


Liferay Builds with ECJ

ECJ, the Eclipse Compiler for Java, is an open source incremental compiler used by the Eclipse JDT. It is an option for Liferay builds and is in many cases faster than Javac or Jikes. The jar for ECJ is included in Liferay release 4.4.0 and later.

Configure the build to use ECJ

In release 4.4.0 and later the file can be modified so ECJ can be used for builds. Simply changing this property is all you need to do, as the jar file for ECJ is included in the release. Here is an example from the build file of release 4.4.2:

    ## Compiler

Simple uncomment the line, using a build.{user name}.properties file, that uses the JDTCOmpilerAdapter

After doing this, you will get an initial build error message:

  Task cannot continue because ECJ is not installed.
  ECJ was automatically installed. Please rerun your task.

This is expected. It has installed the ECJ jar file into your Ant lib directory. Simply rerun your Ant build.



Configure Eclipse IDE to use ECJ

Even though you're using Eclipse, you're using Ant to build Liferay and Liferay's build is not dependent on ECJ. After changing the build property, if You keep getting the error message:

  Task cannot continue because ECJ is not installed.
  ECJ was automatically installed. Please rerun your task.


Do not fear, you simply need to put the ecj.jar file into the lib directory of the Ant plugin directory in your Eclipse install. For example, in my linux install, this directory is:


Copy the ecj.jar file from the similar lib directory from your Ant install.

Back To Work

Company Blogs January 7, 2008 By James Min Staff

I haven't had 3 solid weeks off in a while, and let me tell you. I enjoyed every minute of it.


But I'm back to work today and actually, it feels good too. I love working at Liferay and it really helps that the people I work with are great.


I'm in Chicago on-site for a another client's project. Even though it is unusually warm today, wish me luck in surviving the rest of this winter!

Session Attributes from Journal Content and Velocity

Company Blogs November 30, 2007 By James Min Staff

Need to access session attributes from Velocity?


Well, from a Velocity theme (*.vm), you can simply do something like:









However, what about from a Velocity template in a Journal Content Portlet? Well, thanks to Bchan and Ray Augé, we have LEP-4377 and LEP-4378. Thanks, Bchan! Thanks, Ray!


Some examples of how to do this in a VM template are (from LEP-4378):

- get the portlet-namespace
#set ($namespace = $request.get('portlet-namespace'))

- get a request parameter
#set ($someParameter = $request.get('parameters').get('some-parameter'))

If the parameter has an array or values (checkbox, etc..) the values are in a list.. (because VM doesn't have direct array access)

- get an element from the request param array
#set ($someParameter1 = $request.get('parameters').get('some-parameter-array').get(0))

- get request attribute
#set ($friendlyURL = $request.get('attributes').get('FRIENDLY_URL'))

- get a portlet session attribute
#set ($somePSAttribute = $request.get('portlet-session').get('portlet-attributes').get('com.liferay.util.servlet.SessionMessages'))

- get an application session attribute
#set ($someASAttribute = $request.get('portlet-session').get('application-attributes').get('LIFERAY_SHARED_VISITED_GROUP_ID_RECENT'))


And there you have it. Check out the LEP's for the patches and versions affected.



In Hamburg...

Company Blogs November 30, 2007 By James Min Staff

In Hamburg trying to wrap up a project, and we've been working quite a lot. It's easy to forget how beautiful Hamburg is:






Liferay Web Services - How Do You Do It? (4.3.4)

Company Blogs November 20, 2007 By James Min Staff

A lot of people I run into at trainings and on consulting gigs ask this question:


"How do I access Liferay via Web Services?"


Well, there are 2 basic things you need:

1) A way to get the stubs for Liferay Web Services

2) Some sort of client app to access the portal's services


OK. Honestly, here is the easiest thing you can do to get started: Use Eclipse and download the Web Tools Platform (WTP) plugin. You can use the wizard to generate a Web Services client without writing a lick of code!

The 3 main steps:

1) Generate an Axis web service client

2) Call web services via your generated client

3) Use your generated client to access web services from the ext environment


I took most of this from a pretty good slide that Rich Sezov (who is doing a lot of the new Liferay docs) made. This slide is here: Liferay Web Services

Download that and follow the steps there.

In that example we are using a URL for a stock quote web service (non Liferay). This gets you the WSDL file to do the generation from Eclipse WTP. You need the WSDL file to get started with any web services client. If you've got this working, now the question is: "How do I get the WSDL for Liferay Web Services?"

Here is the URL you need for Liferay:

http://" + userIdAsString + ":" + password + "@localhost:8080/tunnel-web/secure/axis/" + serviceName

So for example, to get Organization data, use this URL:



Look in the database in the User_ table to find an appropriate userId.


It should be as simple as that.



Another way to achieve the above is to use one of the Liferay samples. If you are a Java developer, download this:


Liferay Portal 4.3.4 Web Services Client
Java Stubs for Liferay Services (SOAP, Spring Remoting).


This will give you the jar files you need to access these services. Use these jar files to create a very simple webapp. So for a Tomcat instance, in your webapps directory, you will have a directory for your app, and in that directory it will have a standard WEB-INF (with a web.xml) and index.jsp. Very standard stuff. In WEB-INF/lib you will place all the jars. Especially important is the portal-client.jar. To access Liferay Organization data for example, you will have something like this in your index.jsp:


<%@ page import="com.liferay.client.portal.model.OrganizationSoap" %>
<%@ page import="com.liferay.client.portal.service.http.OrganizationServiceSoap" %>
<%@ page import="com.liferay.client.portal.service.http.OrganizationServiceSoapServiceLocator" %>
<%@ page import="" %>

<th>Organizational Membership</th>

long userId = 0;
try {
    userId = Long.parseLong(userIdAsString);
} catch (Exception e) {

OrganizationServiceSoapServiceLocator locator = new OrganizationServiceSoapServiceLocator();

OrganizationServiceSoap soap = locator.getPortal_OrganizationService(_getURL(userIdAsString, "Portal_OrganizationService"));

OrganizationSoap[] organizations = soap.getUserOrganizations(userId);

for (int i = 0; i < organizations.length; i++) {
    OrganizationSoap organization = organizations[i];
        <td><%= organization.getName() %></td>

private URL _getURL(String userIdAsString, String serviceName) throws Exception {

    // Unathenticated url

    String url = "http://localhost:8080/tunnel-web/axis/" + serviceName;

    // Authenticated url

    if (true) {
        String password = "test";

        url = "http://" + userIdAsString + ":" + password + "@localhost:8080/tunnel-web/secure/axis/" + serviceName;

    return new URL(url);


Lastly, but not LEAST!!!

Another example that Liferay provides is here:


Take a good look at this sample and you will see almost everything you need. I usually am in the habit of telling people to "just look here" but I think it works better with all the above stuff explained first. =)


Hope it works for you and good luck!



My Next Home Project: Linux MCE

Company Blogs November 18, 2007 By James Min Staff

My next home project will be to set up Linux Media Center Edition (MCE) which runs on top of Kubuntu. [Also a wiki here.]







I've been reading up on this alternative to Windows Media Center and WOW... It blows me away! I was initially going to set up MythTV on a linux box, but this package makes things 100X simpler! Plus, this thing does everything. And by "everything" I mean EVERYTHING. Controls your TV/Cable/Satellite, DVDs/CDs, home security, lights, VoIP phone service, media cataloging/ripping/streaming... even allows your media to follow you from room to room! And more... a lot more! Plus you can get a Linux MCE remote with a gyro to point it and control your media (same technology that is in the Nintendo Wii).


Check out this demo video:



 Now that is cool! I want to throw out my TiVo Series 3 HD and SlingBox now! (Well, once I get Linux MCE set up and running...)

Liferay Cribs

Company Blogs November 9, 2007 By James Min Staff

And now a brand new episode of Liferay Cribs...

Just kidding. But this is a non-technical blog post.

For the past year and a half, I feel very fortunate to have been working for Liferay, and I'm just grateful to work with not only very smart people, but just really good people. It's very humbling. I feel genuine concern, from the top-level-on-down, not only for the quality and future of our product and company, but for the employees. It is especilly tough at times doing the consulting gigs and traveling, as it is with any other company, but I feel more community here.

Anyhow, enough of all that... I wish I could post more pics of the city and landscape here in Frankfurt, but the weather is not cooperating these days. It's cold, gloomy, and rainy out... However, here is the corporate apartment that our Director of European Operations set up for me. It's really nice and I feel very lucky to stay there. I feel well taken care of!








Germans are very efficient in everything, and this is reflected in mundane life. And yes, I do have a pretty good refrigerator, it's just hidden. Ha...

Inter Portlet Communication (IPC) in Liferay

Company Blogs November 2, 2007 By James Min Staff

A common question and topic when I do training or work on support cases, is, "What is the right way to do inter portlet communication in Liferay?"

Well, there is no "right way" to do this. At least not yet. This is because IPC was left out of JSR-168. In other words, there is no standard API. As for JSR-286, there will be a IPC standard that will be an event system. IPC is on the Liferay roadmap as well.

For the time being, here are three ways in which IPC can be implemented:


Method 1) The first is to use the request attributes to pass messages between portlets. You can also use session attributes for this as well.

Method 2) We provide a proprietary portlet url tag that allows you to target one portlet to another (cross-linking). It looks something like this:

<liferay:actionURL portletName="xxx" />

Method 3) Use our AJAX toolkit to inject content from one portlet to another. See for more information. You can see how you can use this in conjunction with portlet urls to inject content into a div layer.


The most recommended approach is to use (Method 1) from above, using request or session attributes.

In order for this to work you must have the portlet calling request.setAttribute() and it needs to be doing it within processAction(), so that this executes before the other portlets call render().

Once you do this IPC is complete, the other portlets can pick up the message using renderRequest.getAttribute().



You will have to use a non-ajax approach if you want it to be more flexible. So basically, the trade-off is:

1) non-ajax approach is more flexible

2) ajax approach requires hardcoding of the portlet name in the JSP


Remember, there is no standard or API yet, so we can only give hints on how to implement!


Showing 1 - 20 of 30 results.
Items 20
of 2