How to Override Out Of the Box (OOTB) Modules in Liferay DXP

This blog covers detailed information about creation of Fragment in Liferay DXP and how to execute required overriding.

Liferay DXP, one of the most popular open sources has many out of the box (OOTB) modules and sometimes based on our specific requirement we need to override them. In general, usage of OSGi fragment is the method of performing such overriding.

This blog includes

What is Fragment?

How to create Fragment in Liferay 7

Usage of Fragment in Liferay 7 DXP to:

  • Override Liferay OOTB Module’s JSP
  • Override Language properties
  • Override HTTP request with Servlet Filter
  • Override Liferay Struts actions
  • Override Liferay Modal Listener




What is Fragment?

Fragment is a type of OSGi module similar as mvcportlet, service, activator, panel app etc. It can be said that Fragment is an extension of host module.

For all versions prior to Liferay 7, Hook was being used to override Liferay portlets. But for Liferay 7, we have to use Fragment as Hook. Please note that, Fragments are extended host modules and at the time of deployment, fragment module definitions will be merged in host module (only if, fragment module does not create any conflict with host module). If any kind of conflict is created, fragments will not be included in host module till its resolution. A fragment does not have its own class loaded or bundle activator.

Fragment jar has own OSGi manifest file and that file contains information about OSGi. Please find the significant information of MANIFEST.MF below:

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: Liferay Fragment

Bundle-SymbolicName: azilen.login.fragment.module

Bundle-Version: 1.0.0

Bundle-RequiredExecutionEnvironment: JavaSE-1.6

Fragment-Host: com.liferay.login.web;bundle-version=1.0.5

Import-Package: org.apache.commons.logging;version=”1.0.4″

Export-Package: com.azilen.training;version=”1.0.0″

 

Please find the details of its key properties below.

Fragment-Host: The Bundle Symbolic Name of the host module

Bundle-Version : Initial version of the bundle

Bundle-Version : Human readable fragment module name

Bundle-SymbolicName : Unique identifies the fragment in OSGi container.

Import-Package : External packages which are used in Fragment

Export-Package: Fragment packages which are visible to others modules

Liferay 7 uses Fragment for performing actions such as:

  1. Override Liferay OOTB module’s JSP
  2. Override Language properties
  3. Override HTTP request with Servlet Filter
  4. Override Liferay Struts actions
  5. Override Liferay Modal Listener
  6. Override Liferay Action Command

How to create Fragment in Liferay 7

To create a Liferay fragment as a module, use the below command

blade create -t fragment [-h hostBundleName] [-H hostBundleVersion] projectName

Please note that, we have to specify the type of blade module as fragment with -t parameters. Whereas -h parameter will require host bundle Symbolic name and -H parameter will require version of the host module which is going to be overridden. And last projectName is human friendly fragment module name.

How to Override Liferay OOTB Module’s JSP

Let’s take a Use Case: I want to override Liferay Login module and I want to customize the look and feel according to my requirements. So the blade command to be created will be as below:

blade create -t fragment -h com.liferay.login.web -H 1.0.5 login-fragment-module

Now it will create one skeleton structure of fragment and you can see host module (log in module) symbolic name and version in bnd.bnd file. There can be a query that how to find host module symbolic name and version. To get those details, we have to connect gogo shell with command written

telnet localhost 11311

Then run lb command and it will list all modules deployed in server. You can find host module with his status and version.

219|Active | 10 | Liferay Login Web (1.0.5)

Our fragment structure is ready now and we are all set to override host module jsp. As we need to override login.jsp, let’s copy it from

Liferay-src/modules/apps/foundation/login/loginweb/src/main/resources/METAINF/resources/login.jsp

And paste it in login-fragmentmodule/src/main/resources/META-INF/resources/.

Now modify login.jsp as your requirement and deploy login-fragment-module, after successful deployment, you should get your changes in OOTB login module

How to Override Liferay DXP’s Language properties

Liferay supports multiple languages. Hence, we have language properties for OOTB modules. Suppose we want to change properties values for some labels, error messages, success messages etc. We have flexibility to override those properties value and can change as per our requirements.

Let’s take a Use Case:  We want to change Login portlet authentication failed message.  The property for that message is: authentication-failed. We want to override these properties with our custom message.

blade create -t mvcportlet -p com.azilen.fragment.language -c CustomLanguageComponent languagefragment-module

Please note that, here we are creating -t mvcportlet and not -t fragment because here we will override language properties with Resource bundle class.

CustomLanguageComponent.Java
@Component(
    property = { "language.id=en_US" },
    service = ResourceBundle.class
)
public class CustomLanguageComponent extends ResourceBundle {
    ResourceBundle bundle = ResourceBundle.getBundle("content.Language",UTF8Control.INSTANCE);
    
    @Override
    protected Object handleGetObject(String key) {
        System.out.println("getting key"+key);
        return bundle.getObject(key);
    }
    @Override
    public Enumeration<String> getKeys() {
        return bundle.getKeys();
    }
}

It can be seen that, we are creating our custom class CustomLanguageComponent which extends ResourceBundle and we specify property = {“language.id=en_US”} in @Component annotation. We are pointing out to override Language_en.properties file.

Now Create Language_en.properties under /language-fragmentmodule/src/main/resources/content and add authentication-failed property with our custom messages.

authentication-failed=Authentication failed. Please try again (customized).

Now deploy language-fragment-module and you will get customized message whenever the log in process gets failed in Login Module.

How to Override HTTP Request with Servlet Filter

 Sometimes, we need to intercept http request and need to write logic on that request. So we can achieve it with BaseFilter.

Here we will intercept every request and just print log in processFilter method.

blade create -t mvcportlet -p com.azilen.custom.filter -c CustomFilterPortlet custom filterfragment-module
CustomFilterPortlet.java

@Component(
    immediate = true,
    property = {
        "dispatcher=REQUEST", "dispatcher=FORWARD",
        "servlet-context-name=",
        "servlet-filter-name=Custom Filter",
        "url-pattern=/*"
    },
    service = Filter.class
)
public class CustomFilterPortlet extends BaseFilter {
    private static final Log _log = LogFactoryUtil.getLog(CustomFilterPortlet.class);

    @Override
    protected void processFilter(HttpServletRequest request, HttpServletResponse response,
        FilterChain filterChain)throws Exception {
        log.info(“Intercept request successfully !!!”);
        filterChain.doFilter(request, response);
    }
}

Here CustomFilterPortlet extends BaseFilter and override processFilter method where we can write our logic and we have to specify url pattern as url-pattern=/* in @Component property.

How to Override Liferay Struts actions

 In Liferay 6.2 and other prior versions, all the Liferay actions are being handled by struts action defined in struts-config.xml. On the other hand, in Liferay 7 DXP majority of the actions are converted in ActionCommand. Still Liferay 7 has some struts action defined in struts-config.xml.

If we want to override that particular action then we can override it with StrutsAction.class. Please note only struts actions defined in struts-config.xml file can be overridden by StrutsAction.class.

Here, we will override Terms and Conditions action which gets executed when the user logs in for the first time and he has to accept terms and conditions.

blade create -t mvcportlet -p com.azilen.custom.struts.action -c
CustomTermsOfUseActionPortlet struts-action-fragment
CustomTermsOfUseActionPortlet.Java
@Component(
    immediate=true,
    property={
        "path=/portal/update_terms_of_use"
    },
    service = StrutsAction.class
)
public class CustomTermsOfUseActionPortlet extends BaseStrutsAction {
    private static final Log _log =
        LogFactoryUtil.getLog(CustomTermsOfUseActionPortlet.class);
    @Override
    public String execute(StrutsAction originalStrutsAction, HttpServletRequest request,
        HttpServletResponse response)throws Exception {
        log.info("Calling Custom Termsof Use Action");
        //you logic goes here
        return originalStrutsAction.execute(request, response);
    }
}

Here, CustomTermsOfUseActionPortlet extends BaseStrutsAction and override executes method where we can write our custom logic. We need to specify struts action path which we want to override in property “path=/portal/update_terms_of_use” in @Component.

How to Override Liferay Modal Listener

Sometimes, we may need to override Liferay’s OOTB entity like User, Group, DLFileEntry etc. for operations like onAfterUpdate or onBeforeUpdate. We can override those methods with BaseModelListener<T> class.

Here, we will override Liferay User’s onAfterUpdate method which gets executed when any user will be updated.

blade create -t mvcportlet -p com.azilen.modal.listener.portlet –c CustomUserModalListerPortlet custom-model-listener-module
@Component(
    immediate = true,
    service = ModelListener.class
)
public class CustomUserModalListerPortlet extends BaseModelListener<User> {

    @Override
    public void onAfterUpdate(User model) throws ModelListenerException {
        _log.info("user is updateing... !!!!");
        super.onAfterUpdate(model);
    }
    private static final Log _log =
        LogFactoryUtil.getLog(CustomUserModalListerPortlet.class);
}

Here CustomUserModalListerPortlet extends BaseModelListener<User> and override onAfterUpdate method where we can write our custom logic. We need to define service property value as ModelListener.class in @Component.

There are enormous possibilities of customizing Liferay DXP open source for developing highly scalable modern applications. Programmers find Lifera 7 much interesting as it enables coding to be a creative and logical thinking based process. As a result, Liferay DXP Development is getting increasingly popular among both developers and industries.

Author Bio:

Sandip Patel is a technology enthusiast and certified Liferay & MongoDB professional having 7+ years of experience. He is working with Azilen Technologies and loves to remain updated with latest Liferay technologies and innovations.


0 0 votes
Article Rating
guest
2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Vish
Vish
3 years ago

Hi Sandip; Thank you for your article. It ‘s extremely helpful. I have a problem i hope you can help me solve: I have used tag ( Liferay Frontend Editor CKEditor Web Version: 1.0.45 ) to display WYSIWYG on a page. I am using ckeditor with this input tag. but the default editor is using old version of ckeditor. I want to use the latest version of ckEditor with LF. I don’t know how to do it. I’m using LF 7. Pls help.

Vish
Vish
3 years ago

Here’s the latest version of ckEditor https://ckeditor.com/docs/ckeditor4