Thursday, February 5, 2015

Custom JSON web service in Liferay

We can publish JSON webservice from Liferay portlet or hook by 2 ways (at my knowledge at the time of writing this code).

Way No. 1: using Service builder

 Specify "remote-service="true"" in service.xml like below:

<entity name="Employee" local-service="true" remote-service="true">

and run Liferay->SDK->build-service.
It automatically create some interfaces and classes named: *Service, *ServiceImpl or *ServiceUtil... (These files differ with *LocalService, * LocalServiceImpl or *LocalServiceUtil which are used internally JVM).

JSON service has not exposed yet until you write some functions in *ServiceImpl and run Liferay->SDK->build-service again.

The magic is clearly explained in the websites listed in References. Basically, it will add @JSONWebService to *Service interface. By this way, Liferay can scan and publish function in this interface as an API webservice.

Test it by type: http://your-ip:port/plugin-context-path/api/jsonws. It will list out all your service functions that has been published.

Way No. 2: write custom classes and register to Liferay manually

Liferay portal 6.1 is slightly different with Liferay portal 6.2 in the way it scans service functions.

  • In Liferay 6.1:
Create an interface in your package. One thing should be noted is that this interface has to be suffix by "Service" like: "HelloworldService" and mark with @JSONWebService at class scope definition.

@JSONWebService
public interface HelloworldService {
    public java.lang.String sayHello();
}


Corresponding to Service inferface, Liferay need a "Util" class. It will be the endpoint that catches the request from client.

public class HelloworldServiceUtil {
    public static String sayHello() {
        HelloworldServiceImpl service = null;
        if (service == null) {
            HelloworldServiceImpl invokableLocalService = (HelloworldServiceImpl) PortletBeanLocatorUtil.locate("ws-test-portlet", "hellworld");

            if (invokableLocalService != null) {
                service = invokableLocalService;
            }           
        }
       
        if(service != null) {
            return service.sayHello();
        } else {
            return "null";
        }
    }
}


In this case, HelloworldServiceImpl does not take part in directly to the process of  public JSON service. HelloworldService is used to create signature. HelloworldServiceUtil is to handle request. It calls HelloworldServiceImpl to do the business logic and return the result. As you can see, we can get an instance of "HelloworldServiceImpl" from ext-spring.xml through PortletBeanLocatorUtil.locate().
Noted that functions in HelloworldServiceUtil are all static.

Test it by type: http://your-ip:port/plugin-context-path/api/jsonws.

  • In Liferay 6.2:
Things become simpler. Just create an interface and name it any thing you like.

public interface Helloworld {
    public String sayHello();
}


Implement it by an implementation class:

@JSONWebService
public class HelloworldImpl implements Helloworld {

    @Override
    public String sayHello() {
        return "Hello baby";
    }
}


But put @JSONWebService at implementation class like above.
That's all you have to do.

Both in Liferay 6.1 and In Liferay 6.2, you need add JSON Service servlet in web.xml file:

<filter>
        <filter-name>Secure JSON Web Service Servlet Filter</filter-name>
        <filter-class>com.liferay.portal.kernel.servlet.PortalClassLoaderFilter</filter-class>
        <init-param>
            <param-name>filter-class</param-name>
            <param-value>com.liferay.portal.servlet.filters.secure.SecureFilter</param-value>
        </init-param>
        <init-param>
            <param-name>basic_auth</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>portal_property_prefix</param-name>
            <param-value>jsonws.servlet.</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>Secure JSON Web Service Servlet Filter</filter-name>
        <url-pattern>/api/jsonws/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>JSON Web Service Servlet</servlet-name>
        <servlet-class>com.liferay.portal.kernel.servlet.PortalClassLoaderServlet</servlet-class>
        <init-param>
            <param-name>servlet-class</param-name>
            <param-value>com.liferay.portal.jsonwebservice.JSONWebServiceServlet</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>JSON Web Service Servlet</servlet-name>
        <url-pattern>/api/jsonws/*</url-pattern>
    </servlet-mapping>


Try and happy coding!
-----
References:

http://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/json-web-services

http://www.liferaysavvy.com/2013/11/liferay-custom-json-web-services-on.html

http://www.endeios.io/blog/-/blogs/leverage-liferay-service-s-structure-for-you-own-personal-back-end-s-service

No comments:

Post a Comment