Featured post

Docker setup for Liferay 7 with MySQL

Thursday, 25 August 2016

Portal events in Liferay 7


Portal events or sometimes referred as action in Liferay are of different types.
They executes on different time and a developer can choose relevant action to perform.
You can find these entries in portal.properties-

1) Servlet service event
The pre-service events process before Struts processes the request.
The post-service events process after Struts processes the request.

servlet.service.events.pre
servlet.service.events.post

2) Login Events process after successful login only.

login.events.pre
login.events.post

3) Logout events called after successful logout.

logout.events.pre
logout.events.post

In this post we will be setting landing page in Liferay 7 OSGI way with post login action.
But at the end you will explore that all of the actions can be implemented by a single change of property.

I will be adding class only in the post, you can choose build type from - Gradle/Maven

To add events you need to -
1) Implement com.liferay.portal.kernel.events.LifecycleAction
2) Add annotation
@Component(
immediate = true, property = {"key=login.events.pre"},
service = LifecycleAction.class
)

that's all, you need to do :)

Below is the code you can refer -


package com.sample;

import javax.servlet.http.HttpSession;

import org.osgi.service.component.annotations.Component;

import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.events.LifecycleAction;
import com.liferay.portal.kernel.events.LifecycleEvent;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.struts.LastPath;
import com.liferay.portal.kernel.util.StringPool;

@Component(
  immediate = true, property = {"key=login.events.post"},
  service = LifecycleAction.class
 )
public class LandingRedirectAction implements LifecycleAction {
 public static final Log LOGGER = LogFactoryUtil.getLog(LandingRedirectAction.class);
 @Override
 public void processLifecycleEvent(LifecycleEvent lifecycleEvent) throws ActionException {
  LOGGER.info("PostLogin called");
        HttpSession session = lifecycleEvent.getRequest().getSession();
        session.setAttribute("LAST_PATH", new LastPath(StringPool.BLANK, "/web/guest/landMeOnMoon"));
 }
}


Now, in here if you want to change this action/event to be called on each page just change the property "key" to "servlet.service.events.pre" and add your code accordingly.

You are just done, Try & Enjoy the function.............:)

Monday, 25 July 2016

Osgi Console and commands

Liferay is now fully supporting osgi, So here are some steps to connect with osgi consoles and some basic commands

OSGI console is the way to deploy and manage state of modules/components.



Connect gogo shell


 Enable telnet in windows
Go to command prompt
 command - telnet localhost 11311

OR

use putty with localhost and port 11311



Install osgi web console

Go to gogo shell

command - install 

http://mirror.switch.ch/mirror/apache/dist/felix/org.apache.felix.webconsole-4.2.16-all.jar

OR

command -  install file:///C:/org.apache.felix.webconsole-4.2.16-all.jar

After installing bundle, use the bundle id to start the bundle. By default bundle is in installed state.

command - start [bundle id]

Access - http://localhost:8080/o/system/console/bundles- (admin/admin)

[bundle id] - is an integer which is identifier for particular bundle.



Gogo shell commands


install file:///C:/liferay-blade-samples/maven/hook/target/hook-1.0.0.jar - Install the bundle
diag [bundle id] - Check for issues
update [bundle id] - Pick up from the last location
lb - List all the bundles
 ss - List all the bundles(Different View)
lb [bundle name or part of the string] - List all the bundles with matching string
uninstall [bundle id] - Uninstall the bundle
start [bundle id] - Start the bundle
stop [bundle id] - Stop the bundle
 b [bundle id] - Provides bundle details
refresh [bundle id] - Refresh bundles
disconnect [bundle id] - Disconnect from Gogo shell
inspect  ('capability' | 'requirement') <namespace>  [bundle id] - Inspect the bundle


Osgi Status

INSTALLED - Bundle is available in container
ACTIVE - Bundle is available to use or can be activated lazily
RESOLVED - All prerequisite are available to activate the bundle
STARTING
STOPPING

You are just done, Try & Enjoy the function.............:)

Wednesday, 13 February 2013

Add / Edit Web Content through custom portlet

Hi,

May be you have used it earlier but it was never so easy.

In every project we need to add/edit/delete web content from our custom portlet.
Hope it helps...

<!--

<%@page import="com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil"%>
<%@page import="com.liferay.portlet.journal.model.JournalArticle"%>
<%@page import="java.util.List"%>
<%@page import="com.liferay.portal.util.PortalUtil"%>
<%@page import="com.liferay.portal.util.PortletKeys"%>
<%@page import="javax.portlet.WindowState"%>


<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib prefix="liferay-portlet" uri="http://liferay.com/tld/portlet" %>
<%@ taglib prefix="liferay-ui" uri="http://liferay.com/tld/ui" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>

<portlet:defineObjects />
<liferay-theme:defineObjects />
This is the <b>Add Web Content</b> portlet.

// Add Web Content Link

<liferay-portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="addArticleURL" portletName="<%= PortletKeys.JOURNAL %>">
<portlet:param name="struts_action" value="/journal/edit_article" />
<portlet:param name="redirect" value="<%= PortalUtil.getCurrentURL(renderRequest) %>" />
<portlet:param name="portletResource" value="<%= portletDisplay.getId() %>" />
<portlet:param name="groupId" value="<%= String.valueOf(scopeGroupId) %>" />
</liferay-portlet:renderURL>

<liferay-ui:icon image="add_article" message="add-web-content" url="<%= addArticleURL %>" />

<div>
<%
   List<JournalArticle> listJournalartArticles=JournalArticleLocalServiceUtil.getArticles(scopeGroupId);
   for(JournalArticle journal:listJournalartArticles){
%>

// Edit Web Content Link

<liferay-portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="editURL" portletName="<%= PortletKeys.JOURNAL %>">
        <portlet:param name="struts_action" value="/journal/edit_article" />
        <portlet:param name="redirect" value="<%= PortalUtil.getCurrentURL(renderRequest) %>" />
        <portlet:param name="originalRedirect" value="<%= PortalUtil.getCurrentURL(renderRequest) %>" />
        <portlet:param name="groupId" value="<%=String.valueOf(scopeGroupId)%>" />
        <portlet:param name="articleId" value="<%=journal.getArticleId()%>" />
        <portlet:param name="version" value="<%=String.valueOf(journal.getVersion())%>" />
</liferay-portlet:renderURL>
<liferay-ui:icon image="edit" message="edit-web-content" url="<%= editURL %>" />

<liferay-ui:journal-article articleId="<%=journal.getArticleId()%>" groupId="<%=scopeGroupId%>" />
<%
    }
%>

</div>

-->

With help of above code you can add/edit web content. It will redirect you on same portlet after adding/editing portlet.

You need to make some changes in above code which i used to display  list of web contents so you can get unique one.

Note: If there is a hyphen(-) in your portlet name then it will through an exception in second deployment.
           Either create portlet without hyphen(-) or follow this link to resolve this issue and have hyphens.

You are just done, Try & Enjoy the function.............:))

Tuesday, 6 November 2012

Reset or Recover Admin / User's password by Hook


Sometimes we go through such kind of problem that we lost all the details of Admin user/User or other users and unable to access portal.

One thing we can to rid out of this problem is to change the User_ table directly
 i.e. change it manually.
For That you can follow this link .

But in production we don't have that much access on server side, so what else we can do?
Thanks to Samuel Liu and Lisa Simpson who make this way so easy.

You can create a hook to reset user's password by specifying some properties like user's name, screenName, virtualHost or webId depends on which liferay version you are using.

Here is the link from where you can download/checkout this Hooks as per your liferay version.

If it's not matching your liferay version then create your own hook for this.

1) Create a startup hook.
2) Use PasswordUpdater.java in application.startup.events .



PasswordUpdater.java


package hu.bzz.liferay;

import java.util.Date;
import java.util.Properties;

import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.events.SimpleAction;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.model.Company;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.service.persistence.CompanyUtil;

public class PasswordUpdater extends SimpleAction {

@Override
public void run(String[] arg0) throws ActionException {
Properties props = new Properties();
try {
props.load(this.getClass().getClassLoader().getResourceAsStream("password.changer.properties"));
String type = props.getProperty("type");

                        //If Liferay version is less than 6.1
String virtualHost = props.getProperty("virtualhost");
Company c = CompanyUtil.fetchByVirtualHost(virtualHost);

                        /* If Liferay version is  6.1

                        String webId = props.getProperty("webId");
Company c = CompanyUtil.fetchByWebId(webId);

                         */
User u = null;
String name = null;
if ("screenname".equals(type)) {
String screenName = props.getProperty("screenname");
u = UserLocalServiceUtil.getUserByScreenName(c.getCompanyId(), screenName);
name = screenName;
} else if ("e-mail".equals(type)) {
String emailAddress = props.getProperty("emailaddress");
u = UserLocalServiceUtil.getUserByEmailAddress(c.getCompanyId(), emailAddress);
name = emailAddress;
}
else {
_log.error("You should set type to screenname or e-mail if you want to use the password updater.");
}
String password = props.getProperty("password");
UserLocalServiceUtil.updatePasswordManually(u.getUserId(), password, false, true, new Date());
_log.info("Password for " + name + " was updated.");
} catch (Exception e) {
_log.error(e);
}
}

private static Log _log = LogFactoryUtil.getLog(PasswordUpdater.class);

}


3) create "password.changer.properties" in src and put required details.


password.changer.properties


# type should be e-mail or screenname
type=e-mail

# This is the webId of the company (not of communities or organizations!), if you have 1 instance, it's webId most of the time
webId=liferay.com

# This is the virtualhost of the company (not of communities or organizations!), if you have 1 instance, it's localhost most of the time
virtualhost=localhost

# Read only if the type is e-mail
emailaddress=test@liferay.com

# Read only if the type is screename
screenname=test

password=changeIt



3) Deploy hook & login with new password which you set in property file.
4) After login, liferay will ask to set up a new password.
5) Undeploy the Hook, so it will not set the password again after server restart.

You are just done, Try & Enjoy the function.............:))

Friday, 7 September 2012

Be careful when you assign user management role to any user

Liferay has very fine grained permission system. But some of the issues require much attention from administrator side.

There is a threat i want to let you know that if you assign any user a role of User Management,
that means He/She has all the rights to change all the users information including Administrator.

So, be careful while you assign this kind of permission to any user.

You are just done, Try & Enjoy the function.............:))

ckEditor does not let copy paste microsoft word formatting like tables, colouring inside table cells


Liferay is using ckeditor, but not responsible for any bug ckeditor has.

Let us see first that how this bug stop us to use copy paste function with formatting from MS Word.

1. Log to the system.
2. Go to control panel > Wiki.
3. Create wiki and add wiki page.
4. Open MicroSoft Word.
5. Create tables format them with colours or etc.
6. Click on this word icon

7. Copy and Paste this content from MS Word to ckeditor.

Expected result : It should copy paste all content with formatting.
Actual Result : It will format the content without any formatting.

Workaround :
1) Create a hook of tomcat-6.0.29\webapps\ROOT\html\js\editor\ckeditor\ckconfig.jsp
2) Append below lines in end of file -

CKEDITOR.config.pasteFromWordRemoveFontStyles=false;
CKEDITOR.config.pasteFromWordRemoveStyles=false;

3) Deploy hook & you are done.

You are just done, Try & Enjoy the function.............:))

Monday, 21 May 2012

Create Hook Inside a Portlet, Liferay

Hi Folks,

Yesterday i tried something new, it's easy but useful.

Sometimes we have a requirement where we need a portlet which depends on some extended functionality of Liferay. So in that case we have to create a external hook and provide two wars separately.

Their is an answer, we can create a Portlet which also contains a Hook.


Steps to Go -
1) Create a simple portlet.
2) Put a liferay-hook.xml in WEB-Inf in your portlet.
3) Map the entry, which functionality you want to extend, e.g. portal.properties,stratup-events.
4) Put the require file in place as you put in Hook.

Example : Create a Portlet which extends an startup events by Hook.
1) Create a Hello Portlet.
2) Put liferay-hook.xml in WEB-Inf.
3) Put this entry in liferay-hook.xml file -


<hook>
<portal-properties>portal.properties</portal-properties>
</hook>

4) Create portal.properties in src of Hello portlet.
5) Copy below line to portal.properties -

application.startup.events=com.gomedia.startup.events.StartupAction

6) StartupAction is the class which extends SimpleAction and executes strartup events.

You are just done, Try & Enjoy the function.............:))