Share

Liferay 7 Features

Some of the features highlighting here as of my sight.

  1. Inheritance of categories, vocabularies, application display templates and structures and templates from a parent site.
    Before 7.0 If we want to share structure or template between different sites than we need to put these in global scope.So it will be available to use in other sites also. 
    After 7.0 You will be able to use all the structures, templates, categories, application display templates... etc from any of your parent sites that allows for it (this can be disabled in Site Settings).

  2. Definition of category vocabularies specific to specific Web Content Types or Document Types.
    For example, you can restrict the folder "Sport" to only allow Web Content of type Sport or if you want you can inherit the restrictions of the parent folder:
    Also we can give different workflow for each folder.In this example we are restricting the content that can be added inside this folder to "Sports" and "Basic Web Content", also we are defining a "Single Approver" workflow for "Sports" and no workflow for "Basic Web Content".
  3. Support for Application Display Templates (ADT) to the Login, Language and the Breadcrumb portlets.
  4. Web Content Diffs for comparing web content versions, changes when approving them or receiving an email of the latest changes.
  5. Ability to configure mail notification templates in multiple languages.
    A new liferay-ui:email-notification-setting taglib has been created that should help everyone localize their emails easily by using:
  6. Ability to edit the basic web content structure like any other structure
  7. A cool new quick keyboard navigation to any place in a page.
  8. Update to Bootstrap 3.
  9. SPA Enabler:Build on top of SeenaJs(Liferay Native Library) and AlloyUI Surface
  10. Ability to develop complete portlet as OSGi modules
  11. Ability to use Service Builder in OSGi modules
  12. Ability to expose any Java Service in an OSGi module as a JSON Web Service (even without using Service Builder!)
  13. Support for testing plugins and OSGi modules using Arquillian
  14. Support for JSPs in OSGi modules
  15. Ability to Geolocate Web Content and documents. Also a new template for Asset Publisher to show them in a map.
  16. Improved portal intelligence to predict what user is looking for.They wrote one plugin for CKEditor.You can see in the below image
    The following are considering as of my knowledge
    Autocomplete of users based on screenName
    Autocomplete of friendly urls to site pages
    Autocomplete of related (by site or author) blog entries
    Autocomplete of assets in the document library

Courtesy going to Liferay7 devs and their Blogs

Liferay 7 API changes

The following are some of the things i found out in Liferay7 instance when i installed in my local instance and while using. Here are some of the types of changes
  • Functionality that is removed or replaced
  • API incompatibilities: Changes to public Java or JavaScript APIs
  • Changes to context variables available to templates
  • Changes in CSS classes available to Liferay themes and portlets
  • Configuration changes: Changes in configuration files, like portal.properties, system.properties, etc.
  • Execution requirements: Java version, J2EE Version, browser versions, etc.
  • Deprecations or end of support: For example, warning that a certain feature or API will be dropped in an upcoming version.
  • Recommendations: For example, recommending using a newly introduced API that replaces an old API, in spite of the old API being kept in Liferay Portal for backwards compatibility.


  1. Removed the liferay-ui:journal-article Tag
    Old Code:
    
    
    New Code:
    
    

  2. Removed render Method from AssetRenderer API and WorkflowHandler API
    This affects any Java code calling the method render on an AssetRenderer or WorkflowHandler class, or Java classes overriding the render method of these classes.
  3. Removed Vaadin 6 from Liferay Core.Upgrade to Vaddin 7
  4. Removed Support for runtime-portlet Tag in Body of Web Content Articles
  5. Removed the liferay-ui:control-panel-site-selector Tag instaed of that use liferay-ui:my-sites tag
  6. Changed Exception Thrown by Documents and Media Services When Duplicate Files are Found
    DuplicateFileException changed to DuplicateFileEntryException
    The DuplicateFileException exception was used in two different contexts:
    When creating a new file through D&M and a row in the database already existed for a file entry with the same title.
    When the stores tried to save a file and the underlying storage unit (a file in the case of FileSystemStore) already existed.
  7. The liferay-ui:logo-selector Tag have parameters changes
    Old way :
    
        
        
        
        
    
    
    
    
    New way :
    
    

    Observations:
    Removal of parameter editLogoURL.
    Including (if neccessary) new parameters currentLogoURL, hasUpdateLogoPermission, maxFileSize, and/or tempImageFileName.

  8. Removed get and format Methods which are using PortletConfig as Parameter
    Old way :
    LanguageUtil.get(portletConfig, locale, key);
    
    New way :
    LanguageUtil.get(portletConfig.getResourceBundle(locale), key);
    

  9. Changed the AssetRenderer and Indexer APIs to Include the PortletRequest and PortletResponse Parameters
    The getSummary() method of AssetRenderer and doGetSummary() method of indexer API must include these two parameters as part of method parameters.
    AssetRenderer
    Old way :
    protected Summary doGetSummary(Document document, Locale locale, String snippet, PortletURL portletURL)
    
    New way :
    protected Summary doGetSummary(Document document, Locale locale, String snippet, PortletRequest portletRequest, PortletResponse portletResponse)
    
    Indexer API
    Old way :
    public String getSummary(Locale locale)
    
    New way:
    public String getSummary(PortletRequest portletRequest, PortletResponse portletResponse)
    

  10. The aui:input Tag for Type checkbox No Longer Creates a Hidden Input
    Whenever the aui:input tag is used to generate an input of type checkbox, only an input tag will be generated, instead of the checkbox and hidden field it was generating before.

  11. Changes in Exceptions Thrown by User Services
    Converted into inner classes
    DuplicateUserScreenNameException → UserScreenNameException.MustNotBeDuplicate
    DuplicateUserEmailAddressException → UserEmailAddressException.MustNotBeDuplicate
    ReservedUserScreenNameException → UserScreenNameException.MustNotBeReserved
    ReservedUserEmailAddressException → UserEmailAddressException.MustNotUseCompanyMx, UserEmailAddressException.MustNotBePOP3User, and UserEmailAddressException.MustNotBeReserved
    ReservedUserIdException → UserIdException.MustNotBeReserved
    ContactFirstNameException, ContactFullNameException, and ContactLastNameException → ContactNameException.MustHaveFirstName, ContactNameException.MustHaveFullName and ContactNameException.MustHaveFullName

  12. Removed Trash Logic from DLAppHelperLocalService Methods
    The deleteFileEntry() and deleteFolder() methods in DLAppHelperLocalService deleted the corresponding trash entry in the database. This logic has been removed from these methods.
    Note : The deleteFileEntry() and deleteFolder() methods in TrashCapability not only remove the trash entry, but also remove the folder or file entry itself, and any associated data, such as assets, previews, etc.

  13. Removed Sync Logic from DLAppHelperLocalService Methods
    The moveFileEntry() and moveFolder() methods in DLAppHelperLocalService methods have been removed.These are methods related to Sync events(Liferay Sync).

  14. Removed the .aui name space from bootstrap and upgrading bootstrap to 3.0
    AS we know the pepole who worked in Liferay6.2 they are aware of this thing, this .aui namespace is conflicting with other third party libraries like it exists in Alloy UI also.Which leads to breaking of other functionalities.
  15. Added New Methods in the ScreenNameValidator Interface
    getDescription(Locale): returns a description of what the screen name validator validates.
    getJSValidation(): returns the JavaScript input validator on the client side.
  16. Added Required Parameter groupId for Adding Tags, Categories, and Vocabularies
    addTag in AssetTagService or AssetTagLocalService
    addCategory in AssetCategoryService or AssetCategoryLocalService
    addVocabulary in AssetVocabularyService or AssetVocabularyLocalService
    updateFolder in JournalFolderService or JournalFolderLocalService
  17. Removed the Tags that Start with portlet:icon-
    • portlet:icon-close
    • portlet:icon-configuration
    • portlet:icon-edit
    • portlet:icon-edit-defaults
    • portlet:icon-edit-guest
    • portlet:icon-export-import
    • portlet:icon-help
    • portlet:icon-maximize
    • portlet:icon-minimize
    • portlet:icon-portlet-css
    • portlet:icon-print
    • portlet:icon-refresh
    • portlet:icon-staging

  18. Removed Portal Properties Used to Display Sections in Form Navigators
    • company.settings.form.configuration
    • company.settings.form.identification
    • company.settings.form.miscellaneous
    • company.settings.form.social
    • layout.form.add
    • layout.form.update
    • layout.set.form.update
    • organizations.form.add.identification
    • organizations.form.add.main
    • organizations.form.add.miscellaneous
    • organizations.form.update.identification
    • organizations.form.update.main
    • organizations.form.update.miscellaneous
    • sites.form.add.advanced
    • sites.form.add.main
    • sites.form.add.miscellaneous
    • sites.form.add.seo
    • sites.form.update.advanced
    • sites.form.update.main
    • sites.form.update.miscellaneous
    • sites.form.update.seo
    • users.form.add.identification
    • users.form.add.main
    • users.form.add.miscellaneous
    • users.form.my.account.identification
    • users.form.my.account.main
    • users.form.my.account.miscellaneous
    • users.form.update.identification
    • users.form.update.main
    • users.form.update.miscellaneous

  19. Removed Methods getGroupLocalRepositoryImpl and getLocalRepositoryImpl from RepositoryLocalService and RepositoryService
    Old Call :
    RepositoryLocalServiceUtil.getRepositoryImpl(0, fileEntryId, 0)
    New Call :
    RepositoryProviderUtil.getLocalRepositoryByFileEntryId(fileEntryId)

  20. Renamed ActionCommand Classes Used in the MVCPortlet Framework
    Old Classes
    BaseActionCommand
    BaseTransactionalActionCommand
    ActionCommand
    ActionCommandCache
    New Classes
    BaseMVCActionCommand
    BaseMVCTransactionalActionCommand
    MVCActionCommand
    MVCActionCommandCache
As of now i found these only.Soon i will try to do a post on Liferay 7 Features. Enjoy!!!

Why restart required for deploying Ext plugins?

What happens during the deployment of Ext under hood. It's not same as what happens when other plugins deployed.Let's have a look.Before that please go thorough the Anatomy of Ext to get clear idea
The deploy process creates
  1. ext-impl.jar from the compiled code of ext-impl/src - if  you customize the impl classes
  2. ext-service.jar from the compiled code of ext-service/src - if you customize the service classes
  3. ext-util*.jar from the ext-util-* source folders - if you customize the tag library or utility
  4. Now the deployer starts to copy jars to Liferay's WEB-INF/lib
  5. Before that the first step is deploy portal-*.properties and systeam-*.properties files to Liferay's WEB-INF/classes
  6. At last not but least copies ext-web folder into the deployed liferay's folder
  7. Here i am not using ant for build process so the work done by deployer. If you are using ant you can use ant-deploy(war will be created then manually copy into Liferay deploy folder) and ant direct-deploy(Ext plugin is directly copy to the running Liferay instance and will restart).
Hope you understand why you need to restart the server.

Anatomy of an Ext plugin

The following table represents a Anatomy of Ext.This is a simple structure and purpose of the each directory



Directory
Purpose
xxx-ext/docroot/WEB-INF
All the folders that make up the plugin are in the WEB-INF folder
ext-impl
It contains all source and configuration files except those related to the web application. When an Ext plugin is created, several important files are placed in subdirectories. The most significant are as follows:
  • /src/portal-ext.properties – Used to override the values of the properties in portal.properties
  • /src/system-ext.properties – Used to override the values of the properties in system.properties
  • /src/content/Language-ext.properties – Used to add your own internationalized text messages that ship with liferay portal
ext-lib
Contains any extra dependency libraries
ext-service
Contains the classes that are generated by Liferay’s service builder
ext-util-bridges
Corresponds to the util-bridges folder in the Liferay source
ext-util-java
Corresponds to the util-java folder in the Liferay source
ext-util-taglib
Corresponds to the util-taglib folder in the Liferay source
ext-web
Contains your JSPs, HTML, images JavaScript, and all other web application related files in the subdirectory
  • To add entries to the web application configuration file,edit/docroot/WEB-INF/web.xml
  • To add a portlet,edit /docroot/WEB-INF/portlet-ext.xml, /docroot/WEB-INF/liferay-portlet-ext.xml and docroot/WEB-INF/liferay-display.xml
  • Customizing some of Liferay’s internal StrutsPortlets, the following files will also be of interest to you: docroot/WEB-INF/struts-config.xml and docroot/WEB-INF/tiles-defs.xml

Service Wrapper Hook

Suppose there is a need that I want to add a new method/behavior or change the behavior of existing services then Service Wrapper hook is needed. For this liferay provides a Wrapper class for each service interface.By extending this Service Wrapper we can change / add the functionality for existing service. Lets see how to to this.

1. Create a new hook


2. Create one class which extends wrapper class of interface which we are going to change existing one/adding new API.
import com.liferay.portal.service.UserLocalService;
import com.liferay.portal.service.UserLocalServiceWrapper;
public class CustomUserLocalServiceImpl extends UserLocalServiceWrapper{

 public CustomUserLocalServiceImpl(UserLocalService userLocalService) {
  super(userLocalService);
  // TODO Auto-generated constructor stub
 }

}

3. Now open a liferay-hook.xml || select Service Wrappers in the left panel || Click on Add a Service Wrapper




4. Click on Add a Service Wrapper then you will get following screen where
Service Type :  The existing Liferay service that the Service Impl will wrap
Service Impl :   The custom class which extends Wrapper Class
While giving Service Impl value
  •  If the class already created click browse button and select custom class 
  • Otherwise directly give the class name and click on create button then automatically class will be created.


When you save the file automatically respective xml file tags and its values will be created in the source of this file.You can see source of this file by clicking on the Source tab as follows

    
        com.liferay.portal.service.UserLocalService
        com.liferaygnosis.impl.CustomUserLocalServiceImpl
    

Here CustomLocalServiceImpl class is the extension to the UserLocalService wrapper  class.

5. Now its time to add the new behavior to the existing service by writing the code in our custom class as we created previously.

Its upto you which method you want to override. You can see all the existing methods by going to eclipse menu option Source || Override/Implement Methods, You will get dialogue box where you can select method which you are going to override.

Use-Case:
Here i am overriding the addUser(User user) method.Requirement is while adding the user in liferay i want to create the user in other platforms also like in siebel/CRM. So for that one before adding the user to the Liferay in this i am calling the web service to the siebel server to create user in its platform.
package com.liferaygnosis.impl;

import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalService;
import com.liferay.portal.service.UserLocalServiceWrapper;

public class CustomUserLocalServiceImpl extends UserLocalServiceWrapper{

 public CustomUserLocalServiceImpl(UserLocalService userLocalService) {
  super(userLocalService);
  // TODO Auto-generated constructor stub
 }

 @Override
 public User addUser(User user) throws SystemException {
   /*My custom code to add the user to the siebel */
   SiebelProgramclient.createUser(user);
  return super.addUser(user);
 }

}

6. Now build the hook and deploy it on server.

Enjoy!!!

How to create custom permission in Liferay

1. Create one portlet
2. Create new folder named as reource-actions under docroot/WEB-INF/src
    now create defualt.xml file under resource-actions folder
3. This xml file defines all the resources and their permissions.It is like as follows

	
		permissionsExample
		
			
				ADD_PRODUCT
				ADD_TO_PAGE
				CONFIGURATION
				VIEW
				ACCESS_IN_CONTROL_PANEL
			
			
				VIEW
			
			
				VIEW
			
			
				ADD_ENTRY
				CONFIGURATION
			
		
	

In the above xml we are defining new resource with the id of the portlet in portlet-name tag.
Supports tag : It includes default action items and new one i.e ADD_PRODUCT
action-key : It tells the name of the action
community-defaults : it is deprecated instead of this one site-member-defaults came newly
site-member-defaults : The action items which site members can perform default
guest-defaults : The action items which guest users can perform default
guest-unsupported : The action items which guest users won't perform even can't assign permission to guest by administrators
There are some more tags please go through the DTD

4. Telling to the server register this resource into the permission system by doing the following entry in portlet.properties(create under docroot/WEB-INF/src)


resource.actions.configs=resource-actions/default.xml

5. Associate OR dis-associate a particular role from performing this action. The owner of this resource usually does this operation under Permissions tab of the portlet.

By default permissions

After defining new permissions lets see permissions tab of portlet

If you observe above image a new permission added with the given name but it has the prefix action.XXX
So to get exact name make an entry in Language.properties with the key as action.New Action Key Name


action.ADD_PRODUCT=Add Product

6. Last step is check the permission where ever you want before providing access by using PermissionChecker or PortalPermissionUtil.

Variables available in Layout

The following are the default variables available in Layout


  • $processor
  • $request
  • $themeDisplay
  • $company
  • $user
  • $realUser
  • $layout
  • $plid
  • $layoutTypePortlet
  • $portletGroupid
  • $locale
  • $timeZone
  • $colorScheme
  • $portletDisplay



Creating a Custom Layout

1. Create  a Layout Plugin in Eclipse
2. Open 1_2_3.tpl under docroot
3. Add the following code to the 1_2_3.tpl
 
$processor.processColumn("column-1", "portlet-column-content portlet-column-content-only")
$processor.processColumn("column-2", "portlet-column-content portlet-column-content-first")
$processor.processColumn("column-3", "portlet-column-content portlet-column-content-last")
$processor.processColumn("column-4", "portlet-column-content portlet-column-content-first")
$processor.processColumn("column-5", "portlet-column-content ")
$processor.processColumn("column-6", "portlet-column-content portlet-column-content-last")
I am going to explain the above code as snippets.If you are well aware then see the comments and get easily

Explanation of the snippets

Our requirement is to create a 1-2-3 Layout which means that i am going to take three rows respects to
First row contains one Column
Second row contains Two Columns
Third row contains Three Columns

The page looks like as follows

1. Firstly create a main <div> in the 1_2_3.tpl which it specifies the whole template
 
... ...
Must specify the values for the attributes class,id,role for the <div> and also must specify the id="main-content" and role="main".We can give any value for class

Creating a Row

2.Now create rows in the main <div>.Each child <div> element of main <div> acts as a   one row.As per our requirement we need three rows so lets create three rows by creating three <div> as a child elements of main <div> as follows
......... .........

Create a three <div> elements as like above

Each row <div> must specify the portlet-layout row-fluid CSS class as a class attribute value.

Creating a Column in a Row

3. Each child <div> element of row <div> acts as a one column in a row.As per our requirement we need different columns in different rows so lets take second row where i need to create three columns by creating three <div> as a child elements of row <div> as follows

 
......... ......
........... ...........

Each column <div> has a class attribute values as portlet-column,portlet-column-first span6
portlet-column : Specifies that the respective <div> acts as a Column
portlet-column-first : It represents first column of row
span[] : It represents width of the column in a row.The value should be in between 1 to 12 because it follows 12 cells grid system.


Each column <div> has a id attribute as well.You can identify the column as column-[number]
column-3 : It specifies that the respective column is Third column.

Rendering portlets in the respective columns

4. Include a Velocity template directive to render each column’s portlets. User drops a different portlets in different columns so add the following function in each column of the row

$processor.processColumn("column-2", "portlet-column-content portlet-column-content-first")

It takes two areguments the first is the CSS Column ID and Second is list of CSS Classes.These classes we must pass as arguments.And also has to pass portlet-column-content-[first | last | only as second argument.

Anatomy of Layout

A Layout is single instance of a single page,composed of one or more portlets arranged inside of various columns.A layout is somewhat synonymous with a page.They have a unique internal ID known as the "portlet layout id"

Lets see now Anatomy

Create  a Layout Plugin in Eclipse and you will see as follows


The folder structure is same like other plugins but we have other files like .png, .tpl and .wap.tpl

File Name
Purpose
Liferay-layout-templates.xml
Specifies the name of the template files and the location of their TPL and PNG files
Liferay-plugin-package.properties
Describes the plugin project to Liferay’s hot deployer.
1_2_3.tpl
Generates the HTML structure of the Template
1_2_3.png
Thumbnail image for layout in the UI[Page Layout Screen]
1_2_3.wap.tpl
Variant template for mobile devices


Creating a Layout in Eclipse

1. Open the eclipse which contains Liferay Environment
2. Goto File | New | LiferayPluginProject
3. Give the Project name as 1-2-3-layout then Display name became as 1-2-3-layout.Put the
    default values for Build Type,Plugins SDK and Liferaay Runtime.Select the plugin type as       Layout.

4. Click on Finsish
5. Observe the Project Explorer now,You can have a layout named as 1-2-3-layouttpl as follows