Creating Remote Services with Service Builder

In an earlier learning path, you used Service Builder to generate the model, persistence, and service layers of your application. The services generated by Service Builder come in two flavors: local and remote. Local services, as their name implies, can only be invoked locally. This means that they are invoked from the JVM in which Liferay is running. Remote services can be invoked remotely. They are designed to be used by any web client that can access the services and is permitted to do so. The remote services generated by Service Builder are published as JSON web services when your application is deployed. You can also use Service Builder to generate a WSDL (Web Services Description Language) document for your remote services to make them available via SOAP (Simple Object Access Protocol). Please refer to the Service Builder tutorial for more information.

To specify whether Service Builder should generate local services, remote services, or both, you need to add the appropriate entries to your application’s service.xml file. Open your guestbook-portlet project’s docroot/WEB-INF/service.xml file and examine the tags for the guestbook and entry entities:

<entity name="Guestbook" local-service="true" uuid="true">

<entity name="Entry" local-service="true" uuid="true">

As described in the service.xml DTD, local-service defaults to false while remote-service defaults to true. However, it’s best to specify explicitly whether Service Builder should generate local services and remote services. Other developers who read your service.xml file might not know or remember the defaults. For this reason, add remote-service="true" to the entity tags of the guestbook and entry entities:

<entity name="Guestbook" local-service="true" remote-service="true" uuid="true">

<entity name="Entry" local-service="true" remote-service="true" uuid="true">

To examine the Liferay web services that are currently available on your portal, navigate to [http://[host name]:[port number]/api/jsonws](http://[host name]:[port number]/api/jsonws) (http://localhost:8080/api/jsonws if you’re running Liferay locally on port 8080). By default, the portal’s web service methods are listed. Plugins, however, aren’t in this list, but you can view the web services of a portlet application by changing the context path. For example, to view the web services of the calendar portlet, change to context path from / to /calendar-portlet. Notice that you can’t you change the context path to /guestbook-portlet. Why not? Because you haven’t added any remote service methods to your remote service classes. After you’ve done this and run Service Builder, your services will be available at /guestbook-portlet on the JSONWS API page once you’ve redeployed your portlet.

In an earlier Learning Path, you learned that you expose access to the persistence layer of your application by adding methods to the *LocalServiceImpl classes generated by Service Builder. In the guestbook-portlet project, these classes are GuestbookLocalServiceImpl and EntryLocalServiceImpl. Service Builder generates them initially, but after that doesn’t touch them, because they’re designed for you to use to implement your local service layer.

In a similar way, Service Builder generates *ServiceImpl classes, which are designed for you to implement your remote service layer. In the guestbook-portlet project, these classes are GuestbookServiceImpl and EntryServiceImpl. They’re already sitting there in your project, ready for you to use. To get remote services working for the guestbook-portlet project, use the following steps:

  1. Create a new class in the com.liferay.docs.guestbook.util package called ActionKeys. Add the following code to this class:

     package com.liferay.docs.guestbook.util;
    
     public class ActionKeys extends
                     com.liferay.portal.security.permission.ActionKeys {
    
             public static final String ADD_ENTRY = "ADD_ENTRY";
    
             public static final String ADD_GUESTBOOK = "ADD_GUESTBOOK";
    
     }
    

    The ADD_ENTRY and ADD_GUESTBOOK strings are used to reference the permissions that you defined in the docroot/WEB-INF/src/resource-actions/default.xml file in an earlier Learning Path. It’s a best practice to create strings to refer to your permissions in a class called ActionKeys that extends com.liferay.portal.security.permission.ActionKeys. com.liferay.portal.security.permission.ActionKeys contains strings that are used to refer to portal permissions. These include strings for common permissions such as VIEW, UPDATE, DELETE, etc.

  2. Open the GuestbookServiceImpl class and add the following methods:

     public Guestbook addGuestbook(long userId, String name,
                     ServiceContext serviceContext) throws SystemException,
                     PortalException {
    
             return GuestbookLocalServiceUtil.addGuestbook(userId, name,
                             serviceContext);
     }
    
     public Guestbook deleteGuestbook(long guestbookId,
                     ServiceContext serviceContext) throws PortalException,
                     SystemException {
    
             return GuestbookLocalServiceUtil.deleteGuestbook(guestbookId);
     }
    
     public List<Guestbook> getGuestbooks(long groupId) throws SystemException {
             return GuestbookLocalServiceUtil.getGuestbooks(groupId);
     }
    
     public List<Guestbook> getGuestbooks(long groupId, int start, int end)
                     throws SystemException {
             return GuestbookLocalServiceUtil.getGuestbooks(groupId, start, end);
     }
    
     public int getGuestbooksCount(long groupId) throws SystemException {
             return GuestbookLocalServiceUtil.getGuestbooksCount();
     }
    
     public Guestbook updateGuestbook(long userId, long guestbookId,
                     String name, ServiceContext serviceContext) throws PortalException,
                     SystemException {
    
             return GuestbookLocalServiceUtil.updateGuestbook(userId, guestbookId,
                             name, serviceContext);
     }
    

    Here, for each existing guestbook local service method, you’re adding a corresponding remote service method. For now, the remote service method implementations simply call the local service implementations. By Liferay convention, however, permission checking is added in remote service implementations, because users calling those services aren’t calling them from the app’s UI (which already has permission checks). Since they’re bypassing the UI and going directly to the services, you have to check to see if they have permission to access the data they’re trying to access before you give it to them. You’ll implement permission checking in the next section. For now, you just want to create remote services, confirm that they’re accessible, and confirm that they work.

  3. Open the EntryServiceImpl class and add the following methods:

     public Entry addEntry(long userId, long guestbookId, String name,
                     String email, String message, ServiceContext serviceContext)
                     throws PortalException, SystemException {
    
             return EntryLocalServiceUtil.addEntry(userId, guestbookId, name, email,
                             message, serviceContext);
     }
    
     public Entry deleteEntry(long entryId, ServiceContext serviceContext)
                     throws PortalException, SystemException {
    
             return EntryLocalServiceUtil.deleteEntry(entryId, serviceContext);
     }
    
     public List<Entry> getEntries(long groupId, long guestbookId)
                     throws SystemException {
    
             return EntryLocalServiceUtil.getEntries(groupId, guestbookId);
     }
    
     public List<Entry> getEntries(long groupId, long guestbookId, int start,
                     int end) throws SystemException {
    
             return EntryLocalServiceUtil.getEntries(groupId, guestbookId, start,
                             end);
     }
    
     public int getEntriesCount(long groupId, long guestbookId)
                     throws SystemException {
    
             return EntryLocalServiceUtil.getEntriesCount(groupId, guestbookId);
     }
    
     public Entry updateEntry(long userId, long guestbookId, long entryId,
                     String name, String email, String message,
                     ServiceContext serviceContext) throws PortalException,
                     SystemException {
    
             return EntryLocalServiceUtil.updateEntry(userId, guestbookId, entryId,
                             name, email, message, serviceContext);
     }
    

    Here, you’re doing the same thing for guestbook entries that you did for guestbooks in step 2. You’re simply creating skeleton remote service methods corresponding to existing local service methods. The remote service methods call the local service methods. You’ll add permission checks in the next section.

  4. Run Service Builder (ant build-service) and redeploy the guestbook-portlet project.

Now, navigate to Liferay’s JSONWS page ([http://[host name]:[port number]/api/jsonws](http://[host name]:[port number]/api/jsonws)) and click on the Context Path selector. Notice that /guestbook-portlet now appears as an option. Select the /guestbook-portlet context path and confirm that your remote service methods appear in the list.

Figure 1: After youve added remote service methods to your projects *ServiceImpl classes, run Service Builder and redeploy your project. Then check that your remote services are accessible.

Figure 1: After you've added remote service methods to your project's `*ServiceImpl` classes, run Service Builder and redeploy your project. Then check that your remote services are accessible.

To test that your remote services are working, choose a method to invoke. Pick a simple method that does not require a Service Context parameter, like getGuestbooksCount(long groupId). One easy way to find the group ID of the site to which you’ve added the Guestbook portlet is to use your browser’s developer tools. Open your browser’s developer tools and open the JavaScript console. Enter the following command into the JavaScript console:

Liferay.ThemeDisplay.getScopeGroupId();

Look for the scope group ID (the ID of the currently selected site) to appear in the JavaScript console. Copy it to your system clipboard. Next, navigate to [http://[host name]:[port name]/api/jsonws?contextPath=/guestbook-portlet](http://[host name]:[port name]/api/jsonws?contextPath=/guestbook-portlet) and click on the get-guestbooks-count method.

Figure 2: After youve added remote service methods to your projects *ServiceImpl classes, run Service Builder and redeploy your project. Then check that your remote services are accessible.

Figure 2: After you've added remote service methods to your project's `*ServiceImpl` classes, run Service Builder and redeploy your project. Then check that your remote services are accessible.

Paste the scope group ID that you copied into the group ID field and click Invoke. Confirm that the correct number of guestbooks is returned. Great! Your remote web services are working.

Next, you’ll build a WSDD (Web Service Deployment Descriptor) document for your remote services to make them available via SOAP (Simple Object Access Protocol). In Liferay IDE, open your guestbook-portlet project’s docroot/WEB-INF/service.xml file. Make sure that you’re viewing the service.xml file in Overview mode. Click on the Build WSDD button near the top right corner of the Overview tab of service.xml. Alternatively, right-click on your guestbook-portlet project in the Package Explorer and select LiferayBuild WSDD. When the Ant task finishes, notice that a server-config.wsdd file was created in your project’s WEB-INF directory. This deployment descriptor file describes the services and service methods that your application is publishing.

After the Ant task has finished, re-deploy your guestbook-portlet application, then navigate to the following URL:

http://localhost:8080/guestbook-portlet/api/axis/Plugin_GB_GuestbookService?wsdl

This is a WSDL (Web Services Description Language) document that describes the details about the Guestbook service methods. Such details include, for example, the format of the data that can be sent to and received from the Guestbook web service methods. The following URL contains a similar WSDL document for the Guestbook Entry service:

http://localhost:8080/guestbook-portlet/api/axis/Plugin_GB_EntryService?wsdl

If you’d like to make your application’s services available for remote invocation, generating a WSDD and WSDL documents is an important step. The WSDL documents describe the functionality offered by your application’s web services. If you want to be able to create mobile clients that can access your application’s web services, you must generate WSDD and WSDL documents for your application.

Next, you’ll learn how to secure your web services. Unless you secure your web services by implementing permission checks, any user can add, update, or delete guestbooks or guestbook entries, and you certainly don’t want that.

« Creating Web Services for Your ApplicationImplementing Permission Checks »
Este artigo foi útil?
Utilizadores que acharam útil: 0 de 0