Service Builder

From LiferayPedia

Jump to: navigation, search


Contents

Introduction

Work in progress

This article is a work in progress
If the author has included this page in Contributions Wanted you are encouraged to help improve it.

The Service Builder is a tool built by Liferay to automate the creation of interfaces and classes that are used by a given portal or portlet. This includes code for EJBs, Spring, Persistence, and Model.

The input to the Service Builder is an XML file, typically /ext/ext-ejb/service.xml. For a complete description of the service.xml syntax refer to the well documented DTD at http://www.liferay.com/dtd/liferay-service-builder_4_0_0.dtd.

Value Object Model Classes

Since 4.2, the Service Builder has changed the way value object model classes are generated. Now, interfaces for all model classes are placed into the portal-service.jar. Why would you want to do this? So that the portal-service.jar can be made accessible by WARs that are deployed outside of the classpath of the main code base.

Take for instance the Contact family of classes:

Image:Contact_Model_Class_Diagram.png

All the classes are generated by Service Builder and should not be modified, with the exception of ContactImpl. Let's look at what each of these classes does.

com.liferay.portal.model.BaseModel

This interface is the base interface for all model classes found in Liferay. The only methods defined in this interface identify whether or not this value object model is new. Ultimately, the persistent layer uses this method to determine whether to update or add a new entry in the persistence.

com.liferay.portal.model.impl.BaseModelImpl

This abstract class simply implements BaseModel.

com.liferay.portal.model.ContactModel

This interface provides a representation of a particular entry in the persistence. For example, there can be one ContactModel representing Joe Bloggs and another representing John Smith.

com.liferay.portal.model.impl.ContactModelImpl

This class has the implementation of the methods defined in ContactModel. Note that there is no direct connection to one another.

com.liferay.portal.model.Contact

This interface describes extra helper methods that a developer may find useful when dealing with a given contact. Hence, the developer may want to get the first name or last name of the contact. Note that these entries are not persisted in the Contact_ table but are simply helper methods. This is the value object model that most developers will see -- both returned by the various services and accessible in a separate WAR.

com.liferay.portal.model.impl.ContactImpl

It is here that the developer actually implements the helper methods found in the Contact interface. What is really happening when a helper method is called?

public static String getFullName(
        String firstName, String middleName, String lastName) {

    if (Validator.isNull(middleName)) {
        return firstName + StringPool.SPACE + lastName;
    }
    else {
        return firstName + StringPool.SPACE + middleName +
            StringPool.SPACE + lastName;
    }
}

public String getFullName() {
    return getFullName(getFirstName(), getMiddleName(), getLastName());
}

The getFullName() helper method is actually combining the first name, middle name, and last name of a given contact to form a full name.

So, how do you actually get these method signatures defined in the Contact interface if you are never to edit that file? Service Builder. You simply add the new method to the ContactImpl class, run the build-service target for the corresponding service.xml file and the Service Builder will propagate all the needed signatures.

Service Classes

The class diagram of the MODEL, PERSISTENCE & SERVICE image:Model-service-persistence.jpg

Persistence Classes

Create your own service.xml

The input to the Service Builder is an XML file, typically /ext/ext-ejb/service.xml. For a complete description of the service.xml syntax refer to the well documented DTD at http://www.liferay.com/dtd/liferay-service-builder_4_0_0.dtd.

Create a column with no default datatype

If you look at portal/portal-ejb/classes/com/liferay/portal/service.xml you'll find many examples like this one

<column name="groups" type="Collection" entity="Group" mapping-table="Groups_Orgs" />

from the entity "Organization".

If you'd like to create your own service.xml (e.g. ext/ext-ejb/service.xml) don't reuse this line as it is within your own entity. You'll get this output

     [java] java.lang.ArrayIndexOutOfBoundsException: -1
     [java]     at java.util.ArrayList.get(ArrayList.java:323)
     [java]     at com.liferay.portal.tools.ServiceBuilder.getEntity(ServiceBuilder.java:713)
     [java]     at com.liferay.portal.tools.ServiceBuilder._createPersistence(ServiceBuilder.java:2283)
     [java]     at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:646)
     [java]     at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:330)
     [java]     at com.liferay.portal.tools.ServiceBuilder.main(ServiceBuilder.java:86)

while running 'ant service-build' and your entity won't be created.
The reason is, that the Service-Builder will look for each entity, that does not contain a '.' within it's name, within your 'service.xml'. The entity Group is specified within 'portal/portal-ejb/classes/com/liferay/portal/service.xml', so you have to set up the full qualified name of 'Group' within the entity attribute.

<column name="groups" type="Collection" entity="com.liferay.portal.Group" mapping-table="Groups_Orgs" />

The full qualified name is not the full qualified name of the generated interface

com.liferay.portal.model.Group

It is the path, where the Service-Builder will look after the service.xml.

com.liferay.portal.Group

will be resolved to relativ path

src/com/liferay/portal/service.xml

The Service-Builder assumes, that within this service.xml, the entity Group is declared. If you get an output like this


     [java] java.lang.NullPointerException
     [java]     at java.io.Reader.<init>(Reader.java:61)
     [java]     at java.io.InputStreamReader.<init>(InputStreamReader.java:55)
     [java]     at com.liferay.util.StringUtil.read(StringUtil.java:320)
     [java]     at com.liferay.util.StringUtil.read(StringUtil.java:316)
     [java]     at com.liferay.portal.tools.ServiceBuilder.getEntity(ServiceBuilder.java:731)
     [java]     at com.liferay.portal.tools.ServiceBuilder._createPersistence(ServiceBuilder.java:2283)
     [java]     at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:646)
     [java]     at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:330)
     [java]     at com.liferay.portal.tools.ServiceBuilder.main(ServiceBuilder.java:86)

while running ant build-service, the service.xml could not be found in the path you specified.

See Also

Personal tools