Liferay DXP MvcPortlet and Service Builder

Blog posts

Liferay DXP MvcPortlet and Service Builder

Posted on 28/12/2016 by Alexandros Kazazis

Boy Ohh Boy Let's Do This!

We will make a MvcPortlet with a Service builder which on a button click will store a message in the database and then display it.

Starting with a clear Developer Studio Installation Version 3.0.0.201606202116-ga1

ClearDevStudio

Make sure that you have installed a Jdk

JdkInstall

Create a new Liferay 7 server Liferay portal bundle:liferay-dxp-digital-enterprise-7.0-ga1

NewServer

Then add a new Liferay Workspace Project

WorkSpaceProject

Create a servicebuilder Liferay Module Project inside the Workspace Project

ServiceBuilder

and a mvcportlet Liferay Module Project

MvcPortlet

Configure the service.xml and run the buildService Grandle Task. When the buildService task is done, refresh the project and the new classes will be appeared.

This is how my service.xml looks like

<?xml version="1.0"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 7.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_7_0_0.dtd">
 
<service-builder package-path="com.example">
    <author>Alex</author>
    <namespace>TEST</namespace>
    <!--<entity data-source="sampleDataSource" local-service="true" name="Foo" remote-service="false" session-factory="sampleSessionFactory" table="foo" tx-manager="sampleTransactionManager uuid="true"">-->
    <entity name="Text" local-service="true">
        <column name="numberId" type="long" primary="true"></column>
        <column name="message" type="String"></column>
        <finder name="number" return-type="collection">
            <finder-column name="numberId"></finder-column>
        </finder>
    </entity>
</service-builder>

If you want to add some methods for CRUD in service Builder, run the buildService again.

I added the following method in the TextLocalServiceImpl.java

    public Text addText(String message) {
 
        long numberid = counterLocalService
            .increment();
        Text entry = textPersistence
            .create(numberid);
        entry
            .setMessage(message);
        entry
            .setNumberId(numberid);
        return textPersistence
            .update(entry);
    }

Modify the build.grandle in the MvcPortlet project adding the dependencies with the Service Builder

    compileOnly project("modules:service-builder:service-builder-api")

Continue with the view.jsp and MvcportletmvcportletPortlet.java

My view.jsp looks like this:

<%@ include file="/init.jsp" %>

<portlet:actionURL name="addEntry" var="addEntryURL"></portlet:actionURL>

<form action="${ addEntryURL }" method="post">
    <aui:button name="add"  value="add" type="submit"></aui:button>
</form>
<p>
    <B> We wait for this: ${ message } ${ message1.message }</B><BR>
    <B> Name: ${ name }</B><BR>
    <b> Number: ${ number } ${ number1.numberId }</b><BR>
</p>

and the MvcportletmvcportletPortlet.java:

package com.example.portlet;
 
import com.example.model.Text;
import com.example.service.TextLocalServiceUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.WebKeys;
 
import java.io.IOException;
 
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
 
import org.osgi.service.component.annotations.Component;
 
@Component(immediate = true, property = {
    "com.liferay.portlet.display-category=category.sample",
    "com.liferay.portlet.instanceable=true",
    "javax.portlet.display-name=MvcPortlet Portlet",
    "javax.portlet.init-param.template-path=/",
    "javax.portlet.init-param.view-template=/view.jsp",
    "javax.portlet.resource-bundle=content.Language",
    "javax.portlet.security-role-ref=power-user,user"
}, service = Portlet.class)
public class MvcportletmvcportletPortlet extends MVCPortlet {
 
    private static final Log _log = LogFactoryUtil
        .getLog(MvcportletmvcportletPortlet.class);
 
    @Override
    public void render(
        RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {
 
        ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest
            .getAttribute(WebKeys.THEME_DISPLAY);
        User user = themeDisplay
            .getUser();
        if (user
            .getFirstName() == "") {
            renderRequest
                .setAttribute("name", "Stranger");
        }
        else {
            renderRequest
                .setAttribute("name", user
                    .getFirstName());
        }
        if (renderRequest
            .getAttribute("message1") == null) {
            renderRequest
                .setAttribute("message", "we wait");
            renderRequest
                .setAttribute("number", "we wait for this too");
        }
        else {
            renderRequest
                .setAttribute("message1", renderRequest
                    .getAttribute("result"));
            renderRequest
                .setAttribute("number1", renderRequest
                    .getAttribute("result"));
        }
 
        super.render(renderRequest, renderResponse);
    }
 
    public void addEntry(
        ActionRequest actionRequest, ActionResponse actionResponse)
        throws IOException, PortletException {
 
        try {
            Text result = TextLocalServiceUtil
                .addText("this is what we waited for");
            _log
                .info(result);
            actionRequest
                .setAttribute("result", result);
        }
        catch (Exception e) {
            _log
                .error(e);
        }
 
    }
 
}

Maybe my approach it's not the best, but it works fine in the case.

Now continue with the deployment of the MvcPortlet , Service Builder-api and Service Builder-service.

At this point all things should be good to go. Check if the deployed modules are active with go go shell.

Run the following commands in command line:

telnet localhost 11311 ->enter
lb ->enter

Telnet

If the deployed modules are labeled as active, the application is ready to run.

The portlet should look like this:

Running

and after the click of the button should look like this:

Running2

This entry was posted in Liferay and tagged liferay 7 by Alexandros Kazazis

Comments

In Mvc-Portlet we can access the ServiceBuilder but not the other way around. Our code for the Mvc-Portlet is in MvcportletmvcportletPortlet.java, the code that connects the Mvc-Portlet with the ServiceBuilder lies in TextLocalServiceUtil.java. I hope that helped you, if not try to explain the question a little more in detail because it is not really clear what you want to do.

Instead of two different modules, can we create a single module in Liferay 7, where we can use MVC Portlet and Service Builder at once. When I go through the source code of liferay 7, I found a module "bookmarks" in that I have seen bookmarks-service, bookmarks-api, bookmarks-test and bookmarks-web at one place. Practically is it possible to create like that?

Add new comment

You must have Javascript enabled to use this form.