« Back to Web Services

Web Services via SOAP

Introduction #

In general, web services are resources which may be called over the HTTP protocol to return data. They are platform-independent, allowing communication between applications on different operating systems and application servers. When the database entries are generated by ServiceBuilder, web services can be generated as well based on Apache Axis. As a result, nearly all of the backend API calls can be made using web services. Java clients may be generated from Web Service Definition Language (WSDL) using any number of tools (Axis, Xfire-CXF, JAX-RPC, and so on). Apache Axis is essentially a Simple Object Access Protocol (SOAP) engine—a framework for constructing SOAP processors such as clients, servers, gateways, and so on.

This document will show how to use the web services of liferay portal. Specially, it shows how to build web services and how manage organizations, users, User groups and roles.

Using Web services #

When Liferay portal is up in your local machine, type the following URL in the browser. You will get a list of web services.

http://127.0.0.1:8080/tunnel-web/axishttp://127.0.0.1:8080/tunnel-web/secure/axis

To manage this entityUse this webservice
Web ContentJournalArticle

What's happening?#

The portal uses Apache Axis to generate web services. The default Axis configuration is specified in the server-config.wsdd file under the /portal/tunnel-web/ docroot/WEB-INF folder. When you double-click on the target deploy in the Ant view, the file server-config.wsdd under the /portal/tunnel-web/docroot/WEBINF folder will be merged with the server-config.wsdd file under the /ext/extweb/ docroot/WEB-INF folder. Therefore, when you type http://127.0.0.1:8080/tunnel-web/axis in your browser, you will see a list of SOAP services.

To access a service remotely, the host must be allowed via the portal-ext. properties properties file. After that, the user must have permission to access the portal resources. The default settings to access a service remotely are specified in the portal.properties file as follows:

axis.servlet.hosts.allowed=127.0.0.1,SERVER_IP axis.servlet.https.required=false

The code above shows the IPs to access the Axis servlet. You can input a blank list to allow any IP to access this servlet. SERVER_IP will be replaced with the IP of the host server. By default, 127.0.0.1 is the IP for local host. This is the reason that you can access web services only by the IP 127.0.0.1, and not localhost. Of course, you can use a domain name such as www.bookpub.com if you had set the mapping between 127.0.0.1 and www.bookpub.com in the hosts file.

Build custom WSDD #

Supposed the service.xml is at src/com/ext/portlet/reports of the folder $EXT_HOME/ext-impl.

In order to build custom WSDD, we need to add the following lines after the lines

<target name="build-service-portlet-playerstats"> <antcall target="build-service"> <param name="service.file" value="src/com/xos/playerstats/portal/service.xml" /> </antcall></target>

in $EXT_HOME/ext-impl/build-parent.xml

<target name="build-wsdd-portlet-reports"> <antcall target="build-wsdd"> <param name="service.file" value="src/com/ext/portlet/reports/service.xml" /> </antcall></target>

And use the Ant Target "build-wsdd-portlet-reports" to generate WSDD files.

Add custom operations #

for example:

package com.ext.portlet.reports.service.impl; import com.ext.portlet.reports.service.base.ReportsEntryServiceBaseImpl; public class ReportsEntryServiceImpl extends ReportsEntryServiceBaseImpl { public String LoadArticle () {return "Test";}}

then build services and wsdd as:

ant build-service-portlet-reports

ant build-wsdd-portlet-reports

Build client #

Create a folder ext-client at $EXT_HOME

Add namespaceMapping.properties and build.xml at $EXT_HOME/ext-client

Add build-common-java.xml at $EXT_HOME

Type: ant build-client

namespaceMapping.properties #

com.my.client.soap.portlet.organization.model=http://model.organization.portlet.my.com
com.my.client.soap.portlet.organization.service.http=urn:http.service.organization.portlet.my.com

build.xml#

<?xml version="1.0"?> <project name="ext-client" basedir="." default="compile"> <import file="../build-common-java.xml" /> <property name="jar.file" value="${ant.project.name}" /> <property name="client.url" value="http://localhost:8080/tunnel-web/axis" /> <target name="jar" depends="compile"> <jar jarfile="${jar.file}.jar" > <fileset dir="classes" /> <fileset dir="src" /> </jar> <copy file="ext-client.jar" todir="${project.dir}/ext-lib/development" /> </target> <target name="build-client" depends="clean"> <echo message="Make sure the server is listening on ${client.url}." /> <echo message="" /> <delete dir="src" /> <mkdir dir="src" /> <java classname="com.liferay.portal.tools.PortalClientBuilder" classpathref="project.classpath" failonerror="true" fork="true" newenvironment="true" > <arg value="${project.dir}/ext-web/docroot/WEB-INF/server-config.wsdd" /> <arg value="src" /> <arg value="namespaceMapping.properties" /> <arg value="${client.url}" /> </java> <antcall target="jar" /> </target></project>

build-common-java.xml#

<?xml version="1.0"?>

<project name="build-common-java" xmlns:antelope="antlib:ise.antelope.tasks"> <import file="build-common.xml" />

<if> <and> <equals arg1="${app.server.type}" arg2="tomcat" /> <antelope:endswith string="${app.server.portal.dir}" with="/portal-web/docroot" /> </and> <then> <property name="portal-impl.classes.dir" value="${project.dir}/portal-web/docroot/WEB-INF/classes" /> </then> <else> <property name="portal-impl.classes.dir" value="${project.dir}/portal-impl/classes" /> </else> </if>

<target name="clean"> <delete dir="classes" /> <delete dir="test-classes" /> <delete dir="test-results" /> <delete file="${jar.file}.jar" failonerror="false" /> <delete dir="${java2html.dir}" /> <delete dir="${javadoc.dir}" /> </target>

<target name="compile"> <mkdir dir="classes" />

<copy todir="classes"> <fileset dir="src" excludes="/.java" /> </copy>

<if> <equals arg1="${javac.compiler}" arg2="modern" /> <then> <javac classpathref="project.classpath" compiler="${javac.compiler}" debug="${javac.debug}" deprecation="${javac.deprecation}" destdir="classes" fork="${javac.fork}" memoryMaximumSize="${javac.memoryMaximumSize}" nowarn="${javac.nowarn}" srcdir="src" /> </then> <else> <javac classpathref="project.classpath" compiler="${javac.compiler}" debug="${javac.debug}" deprecation="${javac.deprecation}" destdir="classes" nowarn="${javac.nowarn}" srcdir="src" /> </else> </if> </target>

<target name="jar" depends="compile"> <jar basedir="classes" jarfile="${jar.file}.jar" /> </target>

<target name="java2html"> <java classname="j2h" classpathref="project.classpath" fork="true" > <arg line="-d ${java2html.dir} -js src -m 4" /> </java>

<replace dir="${java2html.dir}"> <replacefilter token="stylesheet.css" value="java2html.css" /> </replace>

<move file="${java2html.dir}/stylesheet.css" tofile="${java2html.dir}/java2html.css" />

<antcall target="javadoc" />

<replace dir="${java2html.dir}"> <include name="/package-summary.html" /> <replacefilter token="/\" value="/" /> </replace> </target>

<target name="javadoc"> <mkdir dir="${javadoc.dir}" />

<javadoc breakiterator="yes" classpathref="project.classpath" destdir="${javadoc.dir}" maxmemory="256m" packagenames="." sourcepath="src" stylesheetfile="${project.dir}/tools/javadoc.css" /> </target>

<target name="deploy" depends="jar"> <copy file="${jar.file}.jar" todir="${deploy.dir}" /> </target> </project> }}}

CRUD on Organizations #

Simple code for Organization:

 import java.net.URL; import com.liferay.client.soap.portal.model.CompanySoap; import com.liferay.client.soap.portal.model.OrganizationSoap; import com.liferay.client.soap.portal.service.ServiceContext; import com.liferay.client.soap.portal.service.http.CompanyServiceSoap; import com.liferay.client.soap.portal.service.http.CompanyServiceSoapServiceLocator; import com.liferay.client.soap.portal.service.http.OrganizationServiceSoap; import com.liferay.client.soap.portal.service.http.OrganizationServiceSoapServiceLocator; import com.liferay.client.soap.portal.service.http.UserServiceSoap; import com.liferay.client.soap.portal.service.http.UserServiceSoapServiceLocator; public class WSTest { public static void main(String[] args) { //reference sql.data.com.liferay.portal.model.ListType.organization.status=12017 try { String remoteUser = "test"; String password = "test"; String serviceOrgName = "Portal_OrganizationService"; String serviceUserName = "Portal_UserService"; String serviceCompanyName = "Portal_CompanyService"; String virtualHost = "localhost"; int statusId = 12017; long regionId = 0; long countryId = 0; long parentOrgId = 0; boolean recursable = true; CompanyServiceSoapServiceLocator locatorCompany = new CompanyServiceSoapServiceLocator(); CompanyServiceSoap soapCompany = locatorCompany.getPortal_CompanyService( _getURL(remoteUser, password, serviceCompanyName)); CompanySoap companySoap = soapCompany.getCompanyByVirtualHost(virtualHost); UserServiceSoapServiceLocator locatorUser = new UserServiceSoapServiceLocator(); UserServiceSoap soapUser = locatorUser.getPortal_UserService(_getURL(remoteUser, password, serviceUserName)); long userId = soapUser.getUserIdByScreenName(companySoap.getCompanyId(), remoteUser); OrganizationServiceSoapServiceLocator locator = new OrganizationServiceSoapServiceLocator(); OrganizationServiceSoap soap = locator.getPortal_OrganizationService(_getURL(remoteUser, password, serviceOrgName)); OrganizationSoap[] organizations = soap.getUserOrganizations(userId); for (int i = 0; i < organizations.length; i++) { OrganizationSoap organization = organizations[i]; System.out.println(organization.getStatusId()+ "\t" + organization.getOrganizationId() + "\t" + organization.getName() + "\t" + organization.getType()); } //ServiceContext scxt = new ServiceContext(); //OrganizationSoap org = soap.addOrganization(parentOrgId, "testOrg-MyOrg_Admin", //"regular-organization", recursable, regionId, countryId, statusId, "My Comments", scxt); //long users[] = {userId}; //soapUser.addOrganizationUsers(org.getOrganizationId(), users); //soap.deleteOrganization(10232); }//

catch (Exception e) { e.printStackTrace();} } Get URL private static URL _getURL(String remoteUser, String password, String serviceName) throws Exception { Unathenticated url String url = "http://127.0.0.1:8080/tunnel-web/axis/" + serviceName; Authenticated url if (true) { url = "http://" + remoteUser + ":" + password + "@127.0.0.1:8080/tunnel-web/secure/axis/" + serviceName; } return new URL(url); }}}}} Note that

1) "sql.data.com.liferay.portal.model.ListType.organization.status=12017" int statusId = 12017; 2) remove all users from the organization, before deleting the organization.

CRUD on Users #

CRUD on User Groups #

CRUD on Roles #

0 Attachments
72167 Views
Average (1 Vote)
The average rating is 1.0 stars out of 5.
Comments
Threaded Replies Author Date
Is there a web service to authenticate..... hariharan t t December 10, 2009 2:07 AM
When I'm trying to create... Heri Parid Pardian February 18, 2010 9:02 PM
I guess...remote-service="true" is mandatory in... Vipul Dave July 5, 2010 4:49 AM
Can you have a custom webservice without using... Abdelrahman Mohamed El Ghanam April 17, 2011 4:57 AM
on a side note: for those of us who use... Shadak aa May 3, 2011 7:57 AM
Implementing a reusable Liferay Service Without... Hans-Joachim Kliemeck May 17, 2011 1:51 AM

Is there a web service to authenticate.. something similar to UserLocalServiceUtil
or
Some web service to get currently logged in user details.
Posted on 12/10/09 2:07 AM.
When I'm trying to create JournalArticleServiceSoap
I've experienced some problem.

what I've done :
ant build-service-portlet-journal
ant build-wsdd-portlet-journal

result:
why All the methods in JournalArticleServiceImpl is not the same as in the JournalArticleServiceSoap

can you tell me why?
Posted on 2/18/10 9:02 PM in reply to hariharan t t.
I guess...remote-service="true" is mandatory in your entity of service.xml.
Posted on 7/5/10 4:49 AM.
Can you have a custom webservice without using the Ext enviroment ??
Posted on 4/17/11 4:57 AM.
on a side note: for those of us who use Netbeans , you have to use axis-1_1 to render the code AND as a library you also need to make the project with JDK1.4 (project properties)
took me 2 days to find this, so thought I'd share this.
Posted on 5/3/11 7:57 AM.
Implementing a reusable Liferay Service Without Ext or Service Builder

http://www.devatwork.nl/2010/04/implementing-a-reusable-liferay-service-w­ithout-ext-or-service-builder/

nice blog!
Posted on 5/17/11 1:51 AM.