4/17/2011

How to create Services in Liferay

I am currently preparing a bigger post. Until it´s release I wanted to share a little "Liferay Service Builder tutorial" with you. It´s one of the basic things you can do in Liferay and one of the reasons why developing with Liferay is some much fun and so flexible.


So ... first: What is the Liferay Service Builder? What does it do ? Do I HAVE to use it ?


To answer in one sentence: The Liferay Service Builder enables you to create in minutes all you need to store and retrieve data in your portlets. This includes table scripts, automatic table creation and CRUD convenience methods to store and retrieve your data.


Normally you create your service in your portlet and that´s it. But you can also allow other portlets to access your service. In this tutorial we will now create a "Hello World" Liferay Service that you can access from all of your portlets.


So before we begin, please create a new portlet called "hello-service-builder" (by using the Liferay IDE)


Create your Service definition.


The first part is to create your service. Create a file called service.xml in your WEB-INF folder. This file will contain all the information about your service.


For our example here we create a service that persists a hello world phrase - a small sentence the user can enter. Add the following to your service.xml:




<?xml version="1.0"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">


<service-builder package-path="de.test">
<namespace>Hello</namespace>


<entity name="HelloWorld" table="helloWorldTable" local-service="true"
remote-service="false">


<column name="helloWorldId" type="long" primary="true" />
<column name="helloWorldPhrase" type="String" />
<column name="createDate" type="Date" />


</entity>


</service-builder>




This is the definition of our service. It will have a primaryKey called helloWorldId, a phrase that we can enter and a createDate so that we know when our phrase got persisted.


By specifying the tableName we can tell the Liferay Service Builder to not autogenerate a tableName. This is very important when you have to access the same table from different portlets. By adding a package-path we specify the packafge, liferay generates the model and service file into. 




Generate the service.


If you have generated the portlet by using the Liferay IDE you will have a build.xml file in the root of your portlet. Please execute the "build-service" target and refresh your workspace.


You should now see a lot of new classes and folders:




As you can see, Liferay generates SQL scripts and classes. If you would deploy the portlet right now, you could see a database table being created instantly - absolutely no need to care for the database.


If you need to have database create scripts for various databases such as mysql, oracle etc. you can execute the ant target "build-db". The ServiceBuilder will then create all the sql scripts you need to create the "Hello World Service" data tables.




Accessing your data


If you have already worked with Liferay Services, you will know, that Liferay allows access to it´s Services always by its XYZLocalServiceUtil classes. They are basically a set of static methods to allow you a convenient way to get your data.


If you take a look at the generated classes you now have, you will see the class HelloWorldLocalServiceUtil which you can use send CRUD commands to the Hello World Service.


I won´t go into much detail here, but the LocalServiceUtil class is all you need to store your data from within your portlet.


Extend your LocalServiceUtil class


If you want to extend the static methods, your autogenerated LocalServiceUtil class provides you, you have to do the following:


Write the methode into the LocalServiceImpl class (for example HelloWorldLocalServiceImpl), the run "buid-service" again, refresh your project / workspace and you will find the method in your LocalServiceUtil. Liferay actually creates interfaces from implementation classes ... not really sure what I should think about that.


One common method, everybody creates in the LocalServiceImpl is an add() - method that takes the parameters your bean will hold, creates an instance of it and persists it in the database.
You can do it like this:



public void addNewHelloWorld(Date createDate, String helloWorldPhrase){

long primaryKey = CounterLocalServiceUtil.increment(HelloWorld.class.getName());


HelloWorld helloWorld= helloWorldPersistence.create(primaryKey);
helloWorld.setCreateDate(createDate);
helloWorld.setHelloWorldPhrase(helloWorldPhrase);
helloWorld.setHelloWorldId(primaryKey);
addHelloWorld(helloWorld);
}



First: Let liferay count your primary key by using the CounterLocalServiceUtil. Second: Let liferay do the initial creation by calling the helloWorldPersistence. Then add your properties and call the "add" method from the HelloWorldLocalServiceBaseImpl class.


That´s all ... you can now start using your very own Liferay Service.




If you like this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.