JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy
  • Contact Us

Using Liferay’s Service Builder, part 2

June 1, 2011 by Krishna Srinivasan Leave a Comment

This article is based on Liferay in Action, to be published on August, 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Introduction

Liferay’s code generator for database persistence, which is called Service Builder, jump-starts portlet development. This utility (which ships as part of Liferay) creates code and SQL for accessing a database from within portlets. Since it uses Spring and Hibernate to implement this, it’s not much different from what you would already do manually, with the important exception that it does much of this “grunt work” automatically, freeing time for you to implement your business logic.

In this article, we’ll continue working with the data layer of a product registration portlet for a fictional company named Inkwell, which we started in part 1 of this series. In part 1, you used Service Builder to generate your persistence objects. Now we’ll see how to use that persistence layer to store and retrieve objects.

How Service Builder works

As shown in figure 1, Service Builder automatically generates several files for you. Among them are both the Data Access Object and the Data Transfer Object layers.

Figure 1 Service Builder generates for you everything from the service layer down. You might need to modify/customize some of this code, but you won’t have to touch most of it. This significantly increases developer productivity.The layer you’ll work with for the most part is the Data Transfer Objects (DTO) layer. This layer talks to the Service Layer, which is automatically generated and allows you to work with objects that need to be persisted or have been retrieved from the database. These are the -Impl classes that you generated in part 1 of this series, and this is the reason why they were placed in your src folder with the rest of your portlet code. You’ll call methods from the Data Access Objects in the persistence layer to do the actual persisting. These methods are generated from the <finder> tags you placed in your service.xml file for Inkwell’s product registration portlet.

Let’s see how this actually works.

Implementing the DTO layer

Though not created yet, Inkwell’s design calls for a form in Edit mode of the portlet. This form allows users to enter products that appear in a dropdown selection box in the actual registration form that makes up the portlet’s View mode. Only two fields will be coming from this form because the third is the primary key, which will be generated:

  • Product name
  • Product’s serial number mask, which is set by the manufacturing department and can be used for field validation

So, how do we get the data the user entered into the database? Remember, we’re after the idea of loose coupling. This means that we don’t want to have any database insertion code in our business logic. So our business logic (when we get to it) will need to call a generic method that has nothing to do with the database. This is where the DTO layer comes in. It acts as a buffer between your business logic and your underlying database code. Service Builder generates both layers, leaving the DTO layer as a stub for you to implement as you wish.

Create a generic method

Presumably, we’ll want a method that has two parameters in the method signature for our two values—the product name and the product’s serial number mask. So let’s create it.

Open the file ProductLocalServiceImpl.java. You’ll find this in a newly generated package called com.inkwell.internet.productregistration.service.impl. This class extends a generated class called ProductLocalServiceBaseImpl (see figure 2).

If you’re using an IDE (such as Eclipse) that does not automatically recognize when another tool adds files, you may need to click on the project name and press F5 to refresh the project in order to see this package.

Figure 2 Service Builder generates both your DAO and DTO layer. Shown above is the DTO layer, which has an instance of the DAO layer (the productPersistence attribute) injected into it by Spring.The first thing we’ll implement in ProductLocalServiceImpl is adding a product. Once you see how that’s done, implementing the other methods will be very simple.

Adding a product

Another great thing about the design of Service Builder is that you never have to touch or modify any of the classes it generates. All of the Spring dependency injection, the Hibernate session management, and the query logic stay in classes you never have to touch. You add code in a class that extends the generated class and, if you add something that changes the interface/implementation contract, those changes are propagated up the chain so the contract is never broken. We’ll see an example of this a bit later. For now, you’ll see that this file is just an empty stub. This is because you have yet to implement anything. So we’ll implement our first method, which will take the values passed to it and call the underlying database code to persist the data to the database (listing 1).

Listing 1 Adding a product to the database
[code lang=”java”]public Product addProduct(PRProduct newProduct, long userId)
throws SystemException, PortalException {
PRProduct product = prProductPersistence.create(counterLocalService.increment(PRProduct.class.
GetName())); 1
resourceLocalService.addResources(newProduct.getCompanyId(),
newProduct.getGroupId(), userId,
Product.class.getName(), product.getPrimaryKey(), false, true, true); 2
product.setProductName(newProduct.getProductName());
product.setSerialNumber(newProduct.getSerialNumber());
product.setCompanyId(newProduct.getCompanyId());
product.setGroupId(newProduct.getGroupId());
return prProductPersistence.update(product, false);
}

#1 Create empty object
#2 Create permissions resources[/code]
The first thing we do (#1) in this method is create a new Product object. Product is the Interface (inherited from PRProductModel), and PRProductImpl (which extends PRProductModelImpl) is the implementation. Note that all we have to do is specify the Interface here since a Factory design pattern is used to create the object for us using the prProductPersistence object that has been injected into this class by Spring. The interface and implementation of this object were both generated automatically by Service Builder, and the fields within the object map directly to the fields in the PRProduct table that we defined. To obtain a new instance of this object, we call a create method, which was also generated by Service Builder.

Because Liferay is database agnostic, it does not use any database-specific means of generating primary keys for its database. Instead, it provides its own utility for generating primary keys. Since the create method that was generated requires a primary key, we need to call Liferay’s Counter utility to generate this. Here’s the cool thing about how this is done: the Counter is automatically injected into the class we’re working on. Why? Because, if you’re doing work with databases and Service Builder, you’re 100 percent likely to need the Counter to create new objects that will be persisted.

Notice that in #2, we next make a call to resourceLocalService to persist resources. Resources are used to define permissions on the objects that are persisted. We added CompanyId and GroupId fields to our tables in order to make our portlet a non-instanceable portlet and to enable us to later implement Liferay’s permissions system.

These two variables track the portal instance and the community/organization, respectively. For example, say a user adds our portlet to a page in the Guest community of the default portal instance. Users then begin adding Products to the database. Because we’ve added the Company ID and the Group ID to the product entities, users can add our portlet to another community, organization, or portal instance and the set of records returned will be different based on the Company ID and Group ID. Our Finder methods filter the records being returned by Company ID and Group ID.

This is how Liferay allows you to place, for example, a Message Boards portlet in two different communities, and have completely different content in each. We’ll do the same thing as we write our portlet.

Once we have our object, it’s a simple matter to set the proper values in the object and then persist it to the database. We then return the object that we’ve created back to the layer that called this method in the first place.

But we’re not quite done yet.

Propagating your changes up the chain

Recall that changes to the interface/implementation contract get propagated up the chain automatically by Service Builder. We were just working in an implementation class, which extends another class, which we call a -BaseImpl class. All of the methods generated by Service Builder have entries in their Interfaces and actual implementations in their BaseImpl class. If developers wish to add more, they’re added in the -LocalServiceImpl class.

Because we’ve just added a new method to a class that implements an Interface, there is no method stub in the Interface for the method we just created. To continue without errors, we need to run Service Builder again. This can be done by running the build-service Ant task. When you run the task, Service Builder will regenerate the interface, which is called PRProductLocalService, to include a stub for the method you created in the implementation class.

This is generally the point where people scratch their heads and say, “Isn’t this backwards? Aren’t you supposed to define the Interface first and then write the implementation?”

In a sense, yes, that’s correct. But, remember that we’re working with a code generator, and it’s that code generator’s job to make things easier for us as developers. By using Service Builder, we are defining the Interface first, as much as we can do that up front. We did this in one step, when we defined our database table in service.xml. Service Builder generated our Interface as well as our default implementation—as best as it could guess at what we needed. That’s what went in PRProductLocalServiceBaseImpl.java. If you need further customization—and you generally do—you can add your own methods. These need to be added to a class that is free of the code generator, so that your changes don’t get overwritten. So PRProductLocalServiceImpl.java is provided as a DTO layer, which allows you to add any methods you may need.

You’ll generally only need to make customizations in one class: the -LocalServiceImpl class. In some cases, you may need to make customizations in -Impl classes in the model.impl package. The only thing we need to worry about right now is the -LocalServiceImpl class.

Now that we’re done with adding products, let’s try deleting products.

Deleting Products

If you think about how you might want to delete products, there are two ways:

  • You already have a Product object, and you just want to delete it.
  • You have a Product’s primary key, and you want to delete it that way without having to retrieve the whole Product.

To make things easier for us in the Controller layer, we’ll overload the delete method by creating versions of it that can handle both cases:
[code lang=”java”]public void deleteProduct(long productId, long companyId)
throws NoSuchProductException, SystemException, PortalException {
PRProduct product = prProductPersistence.findByPrimaryKey(productId);
deleteProduct(product, companyId);
}
public void deleteProduct(Product product, long companyId)
throws PortalException, SystemException {
resourceLocalService.deleteResource(
companyId, Product.class.getName(),
ResourceConstants.SCOPE_INDIVIDUAL, product.getPrimaryKey());
productPersistence.remove(product);
}[/code]
What we’ve done here is enable us to delete a PRProduct using its primary key or the object itself. If we’re using the primary key, we’ll first retrieve the PRProduct object and then call deleteProduct on it. Note that we delete the resource as well as deleting the product. This keeps Liferay’s permissions tables free of “dead” data that might otherwise be left there simply taking up space. When you’re finished modifying your -Impl class, run Service Builder again using ant build-service. As before, this adds your new methods to the interface.

The only thing remaining to do is to query the database for the products we’ve entered because, presumably, users will want to view them and/or edit them.

Querying the database

Just like adding and deleting, getting products out of the database is really easy. You’ll probably remember that we had Service Builder generate a finder for this, which queries the database for products by the GroupId. We always want to query by GroupId because our portlet is non-instanceable. So we’ll implement this in our DTO layer like this:
[code lang=”java”]
public List&lt;PRProduct&gt; getAllProducts(long groupId)
throws SystemException {
List&lt;Product&gt; products = prProductPersistence.findByGroupId(groupId);
return products;
}[/code]
This will return a List of PRProducts, which can be used in the UI layer to display products for viewing or editing purposes. And, as you can see, whatever calls this method (it will be our portlet class) does not need to know anything about JDBC or databases. It’s simply requesting a List. This frees you to do something like swap out Service Builder later, if you find that it doesn’t meet your needs.

Summary

Service Builder makes it easy to generate a whole persistence layer of an application. Using well-known design patterns such as Data Access Objects and Data Transfer Objects, it not only implements a consistent design but also helps the developer to do so. Finders are automatically generated, which allow developers to access their data as Java objects.

Filed Under: Liferay Portal Tagged With: Liferay Portal

Using Liferay’s Service Builder, part 1

June 1, 2011 by Krishna Srinivasan Leave a Comment

This article is based on Liferay in Action, to be published on August, 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Using Liferay’s Service Builder, part 1

Introduction

If you’re an experienced developer, it’s likely that you’ve dealt with a data-driven application before. Liferay ships with a tool called Service Builder, which makes the creation of data-driven applications very easy. I highly recommend that you use Service Builder when writing applications on Liferay’s platform because it will get you going very quickly. How? By generating a lot of the database plumbing code for you so you can concentrate on your application’s functionality.

A database-persistence code generator

With Service Builder, you can simply define a database table in an XML file. Based on that definition, Service Builder then generates the entire Hibernate configuration, the entire Spring configuration, finder methods, your model layer, the SQL to create the table on all leading databases, and your entire Data Access Object layer at one fell swoop. Figure 1 illustrates this.

Figure 1 Service Builder is a tool that sits on top of Hibernate and Spring, automatically generating both configurations for you, along with the Java code necessary to persist your entities to the database.This tool is an excellent database-persistence code generator, which makes it easy to define new tables and to manipulate the data through select, insert, update, and delete operations. Service Builder uses a combination of standard technologies—Hibernate and Spring—that Java developers use every day.

Did you know?

Service Builder is a proven tool that produces code suitable for enterprise deployments. In fact, all of Liferay’s internal database persistence is generated using Service Builder.

If you’re like me, I know what popped into your head as soon as I said “code generator.” It was, “Oh, no. Code generators are bad.” And then you began justifying that statement with many sound, accurate, and excellent arguments. Believe me, I agree with you. But Service Builder is different. From one code generator “hater” to another: Service Builder is designed to enable you to write custom code, not prevent it. It just takes care of the mundane stuff you hate writing, anyway. That is a code generator I’m on board with. I think you’ll like it, too.

We’re going to create a product registration application for a fictional company named Inkwell. This application is designed to replace those warranty registration cards that ship with electronic equipment. You’ll use Service Builder to generate the database tables as well as database persistence. To start, you’ll create that one XML file that is the key to generating the rest of the code.

Creating the service.xml file

Create a file called service.xml in the WEB-INF folder of your project. This file will contain your table definitions. You’ll populate this file with all the information Service Builder needs to generate the SQL for the table—for all the databases Liferay supports as well as database persistence objects you can use in your Java code.

We’ll use the simplest of the tables as our example, which is the Product table. The following listing defines the table for Service Builder.

Listing 1 Defining the Product table using Service Builder
[code lang=”xml”]<?xml version="1.0" encoding="UTF-8" ?>
<!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="com.inkwell.internet.productregistration"> 1
<author>Rich Sezov</author> 2
<namespace>PR</namespace> 3
<entity name="PRProduct" local-service="true" remote-service="false"> 4
<column name="productId" type="long" primary="true" /> 5
<column name="productName" type="String" /> 6
<column name="serialNumber" type="String" />
<column name="companyId" type="long" /> 7
<column name="groupId" type="long" />
<order by="asc"> 8
<order-column name="productName" />
</order>
<finder name="G_PN" return-type="Collection"> 9
<finder-column name="groupId" />
<finder-column name="productName" />
</finder>
<finder name="GroupId" return-type="Collection">
<finder-column name="groupId" />
</finder>
<finder name="CompanyId" return-type="Collection">
<finder-column name="companyId" />
</finder>
</entity>
</service-builder>

#1 Java package for code
#2 Author for JavaDoc
#3 Namespace for tables
#4 Name of entity
#5 Primary key
#6 Additional fields
#7 Foreign Keys
#8 Order data is returned
#9 Finder methods[/code]
This file is pretty easy to read, so we’ll attack it section by section instead of line by line.

DEFINE JAVA PACKAGE

You can define the Java package (#1) into which Service Builder generates the code that powers this database table. Service Builder also generates JavaDoc, and the name you place in the Author tags (#2) will wind up in the JavaDoc as the author of the code. By default, tables you define with Service Builder will go in the Liferay database. To set them apart from the rest of Liferay’s tables, you can prefix them with a namespace (#3). This table, when created, will actually be called PR_PRProducts in the database.

DEFINE ENTITY

Now we get to the cool stuff. The database entity—which, for us, is a Product—is defined using the Entity tag (#4). The two parameters in this tag define how you want Service Builder to generate the service that retrieves and saves these entities. At minimum, you need to have a local service, but you can also have a remote service. This is not an EJB. It is instead a web service, complete with a WSDL document describing it so that your service may participate as part of a Services Oriented Architecture (SOA).

DEFINE COLUMNS

Next, we define the columns and finder methods. Our first column (#5) is defined as a primary key in the database. Other fields we want to store come next (#6). We are also defining two foreign keys (#7): a companyId and a groupId. The DBA team did not specify these two foreign key fields in the tables, but we added them anyway. These fields are internal to Liferay and are used for context purposes in non-instanceable portlets. The companyId corresponds to the portal to which the user has navigated, and the groupId corresponds to the community or organization to which the user has navigated. Since we will be using these field values as parameters in all of our queries, our portlet will have different data in different portals, communities, and organizations.

Quick test

Without reading the next sentence, answer this question: Is our portlet instanceable or non-instanceable? The portlet is non-instanceable because we’ll be using these fields to make sure that the portlet ties all data to the portal and to the community or organization upon which the portlet is placed.

#8 defines a default ordering of the entities when they are retrieved from the database. You can choose to have them returned in ascending or descending order. You aren’t limited to one column here; you can specify multiple columns, and the ordering will happen by priority in order of the columns.

DEFINE FINDER METHODS

The finder methods (#9) actually go and retrieve the objects. Specifying these finders means that Service Builder will automatically generate methods that retrieve objects from the database using the parameters you specify in the finder. For example, the first finder returns Products by groupId and productName.
Now that you’ve defined your table, it’s time to run Service Builder.

Running Service Builder

Save the service.xml file and then run the Ant task called build-service. You’ll see several files get generated and the task will complete with a BUILD SUCCESSFUL message. If you’re using an IDE that compiles source files automatically, you’ll notice errors suddenly appear in your project. Don’t worry about this; it’s easy to fix.

What has happened is that Service Builder generated several Java source files. Some of them are in your existing src folder. Others are in a new source folder called service that it also generated. This folder will resideinside of WEB-INF like the src folder you already have. To fix the errors in your project, just use your IDE’s facility to add another source folder to your project. You may also need to refresh your project. Once you do that, the errors will go away.

Service Builder divides the source it generates into two layers:

  • An interface layer gets generated in the aforementioned service folder. You’ll never change anything in the interface layer manually; Service Builder always generates the code that’s found there.
  • An implementation layer gets generated in your src folder and is initially just skeleton code that allows you to implement the functionality you need.

You’ll notice that there’s also a new file in the root of your src folder called service.properties. This file was also generated by Service Builder. It contains properties that Service Builder needs at runtime to perform its functions. The most important of these properties is a list of Spring configuration files that were also generated.

Another new construct that was generated was a META-INF folder in your src folder. This folder contains all of the XML configuration files that Service Builder needs, including Spring configuration files and Hibernate configuration.

What all of this means is that Service Builder has taken care of your database persistence configuration for you. If you’ve ever used Hibernate alone or the combination of Hibernate and Spring, you know that there are multiple configuration files to juggle between the two. Service Builder automatically configures all of that for you and provides you with static classes that you can use to perform your database persistence functions. It provides both a Data Access Object (DAO) layer and a Data Transfer Object (DTO) layer for you automatically.

Summary

Liferay’s code generator for database persistence, which is called Service Builder, jump-starts portlet development. This utility (which ships as part of Liferay) creates code and SQL for accessing a database from within portlets. Since it uses Spring and Hibernate to implement this, it is not much different from what developers would already do manually, with the important exception that it does much of this “grunt work” automatically, freeing time for developers to implement their business logic.

In part 2 of this 2-part series, I’ll show you how to provide the functionality in your DTO to keep your portlet code from being dependent on anything related to SQL databases.

Filed Under: Liferay Portal Tagged With: Liferay Portal

Loosely Coupled Data Persistence with Liferay

June 1, 2011 by Krishna Srinivasan Leave a Comment

This article is based on Liferay in Action, to be published on August, 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Introduction

Liferay’s Service Builder encourages the proper layering of functionality within a portlet application. Generally, when building an application, it’s good practice to separate the various layers of the application: UI, model, persistence, and so on. This is sometimes called separation of concerns. By keeping the layers as separate as possible, you gain the ability to change the implementation of any one layer more easily—if for some reason you find a better way to do it later.

To some, this must seem like some unnecessary work, but let me give you an example as to why this is important.

The spaghetti code story

Suppose you have a poorly designed application that consists of only two layers—your JSPs and your portlet class. You develop the application by creating action URLs in your JSPs, which correspond to various methods within the portlet. These methods use JDBC to connect to a database and select, insert, update, and delete data. Your database, validation, and page navigation code is all in the portlet or the JSPs, resulting in very large files with lots of logic in them. You test the portlet as well as you can, and it then gets deployed to production.

Within the first day of its use, a bug is found. Your application has a last name field, and a user tried to insert the last name O’Bannon. Because you coded all of your database interaction manually, you forgot that sometimes you need to escape out certain characters. In this case, the apostrophe in the name is causing your database insert to fail.

With the poor design you used for your portlet, you’ll now have to modify the Insert and Update methods of your portlet class and add some code that checks the values your users are inserting for apostrophes. This is an example of a tightly-coupled design: your database code is inside your portlet, so your implementation of code that communicates with the database is intertwined with your business and display logic. Because you were recently working on this portlet, you know where the problem is and so you fix it and redeploy the application. The users work with it for several months before another bug is found. It seems that, somewhere in the portlet, a database connection isn’t being closed and is causing the database server to run out of connections.

Now some significant time has passed, and you’re onto another project. You don’t remember exactly what you did when you wrote this one. You now have to slog through mounds of spaghetti code in your one portlet class looking for the problem—database code mixed in with all kinds of other functionality, such as JavaScript functions, field validation code, database access code, and so on. It’s become a hard-to-maintain mess. After hours of debugging, you finally find the condition where the database connection wasn’t being closed and it was part of a long block of if-then-else conditions, which included field validation logic, business logic, and persistence logic. It took you almost an entire day to find this one problem, because it was buried in a lot of code that should have been separated out into different layers of code logic.

If you had properly layered your application so that the UI code was in one place, the business logic was another, and the persistence logic was in another, you’d have a much more maintainable project. And you might decide at that point that you could use something like Hibernate for your database persistence, and you’d only have to replace a few classes in the one layer. Doing that would solve all of your persistence problems, because Hibernate escapes characters and closes connections automatically. You might then go another step further and replace your homegrown application logic with an MVC framework like JSF or Struts. On each refactor, you could modify one layer of your application at a time. Let’s see how to do that for the persistence layer.

Using two layers for persistence

While the above is a simplistic example, it serves as an example we can use to show how Service Builder encourages proper separation of concerns. For database persistence, two of these layers are the Data Access Object and the Data Transfer Object (see figure 1). These two layers can be written by developers manually, and often a lot of time is spent writing and debugging code in this layer. Service Builder automatically generates both layers for you.

Figure 1 Service Builder generates for you everything from the service layer down. You’ll need to modify/customize some of this code, but you won’t have to touch most of it. This significantly increases developer productivity.With Liferay, the layer you’ll work with for the most part is the Data Transfer Objects (DTO) layer. This layer talks to the Service Layer, which is automatically generated, and allows you to work with objects that need to be persisted or have been retrieved from the database. You’ll call methods from the Data Access Objects (DAO) in the persistence layer to do the actual persisting. In another article, I’ll walk through how this actually works.

Filed Under: Liferay Portal Tagged With: Liferay Portal

Liferay Portal Enterprise Intranets

May 7, 2008 by Krishna Srinivasan Leave a Comment

Chat and Instant Messaging

In the intranet website book.com of “Palm Tree Publications”, as an administrator, you are required to provide an environment for employees to enjoy chatting, instant messaging, mailing, and SMS text messaging with others. This chapter will introduce to us, how to enjoy instant messaging. Then, it will discuss how to manage emails. Finally, it will focus on SMS text messenger.

By the end of this chapter, you will have learnt how to:

  • Add a participant for chatting.
  • Manage (view and delete) participants in the chat portlet.
  • Start chatting.
  • Set up chat portlet.
  • Manage (check, delete, forward, reply, search) mails.
  • Set up mail portlet.
  • Manage SMS text messenger portlet.

Working with Chat Portlet

In order to let employees enjoy chatting and instant messaging with others, we should use the Liferay Chat portlet. Let’s experience how to enjoy chatting and instant messaging first.

As an administrator of “Palm Tree Publications”, you need to create a Page called “Instant Messaging” under the Page, “Community”, at the Book Lovers Community

Adding a Participant

First of all, log in as “Palm Tree” and do the following:

  1. Add a Page called “Instant Messaging” under the Page, “Community” at the Book Lovers Community Public Pages, if the Page is not already present.
  2. Add the Chat portlet in the Page, “Instant Messaging” of the Book Lovers Community where you want to set up chatting and an instant messaging environment, if Chat portlet is not already present.

After adding the Chat portlet, you can view it as shown in the following figure.

liferay-1Then, we need to add a participant in the Chat portlet. As an editor at the Editorial department, “Lotti Stein” wants to ping the manager, “David Berger”, online and further share some comments about Liferay books. Let’s do it as follows:

  1. Login as “Lotti Stein” first.
  2. Go to the Page, “Instant Messaging”, ” under the Page, “Community”, at the Book Lovers Community Public Pages.
  3. Click on the Add icon.
  4. Input a participant’s email address, such as “david@book.com”.
  5. Press the Enter key.

You will see the participant’s full name appear, such as “David Berger”. After adding more participants, such as “John Stuckia” and “Rolf Hess”, you can view all participants as shown in the following figure.

liferay-2

Managing Participants

All the Users you’ve invited will appear as a list of participants. If the User “David Berger” is online ,then the icon to the left of the User name becomes light blue. Otherwise, it remains light gray; for example, User “John Stuckia”. As shown in the following figure, only two Users (“David Berger” and “Lotti Stein”) are online in the server. For details about OpenFire, refer to the forthcoming section.

liferay-3The participants are removable. For example, “Lotti Stein” wants to remove a participant “Rolf Hess”, from the list of participants. Let’s do it as follows:

  1. Locate the participant, such as “Rolf Hess”.
  2. Click on the icon to the left of the User name, such as “Rolf Hess”. You will see that the participant “Rolf Hess” is highlighted.
  3. Click the Remove icon. This participant will be removed from the list of participants.

liferay-4
In short, to remove a User from the list of participants, simply locate the User you want to remove by clicking on the icon to the left of the User name. Then, click the Remove icon. The selected User name will be removed from the list of participants.

Starting Chatting

Irrespective of whether the participants are online or not, you can begin to Chat with them. For example, as an editor of editorial department, “Lotti Stein” wants to start chatting with the manager, “David Berger”. Let’s do it as follows:

  1. Locate the participant, “David Berger”.
  2. Click the User name, ,”David Berger”.
  3. A Chat box will appear.
  4. Input the message, “David, how are you?”
  5. Press the Enter key. Your messages will appear starting with the keyword, Me, in the message box (as shown in the following figure).

liferay-5As a manager of the editorial department, “David Berger” will have to do the following, to receive the messages from “Lotti Stein”:

  1. Login as “David Berger” in new browser.
  2. Go to the Page, “Instant Messaging” under the Page, “Community” at the Book Lovers Community Public Pages.
  3. Locate the participant, “Lotti Stein”.
  4. Click the User name, “Lotti Stein”.
  5. 5. A chat box will appear with the messages from “Lotti Stein”.
  6. Input the message, “I am fi ne, and you?”
  7. Press the Enter key. Your messages will appear starting with the keyword “Me:” in the message box and the messages sent by the other User, Lotti Stein” here, will appear starting with the User’s name as shown in the following figure:

    liferay-6Generally, to start chat, locate the User you want to chat with, by the User name first. Click on the User name link. A Chat box will appear. You can chat with many Users at the same time. To do this, just click on the Users’ name link. Each Chat box is only for one unique User.

The Chat box contains the User’s name on the upper left. You can close the current Chat box by clicking on the mark X to the upper right.

Note that the Chat box is hidden in your current Page initiatively. Whenever a new message comes from the User, you are chatting with, the Chat box will pop up with the new message and possible previous messages.

To send messages, simply input your messages in the message input box fi rst, and then press the Enter key. Your messages will appear starting with the keyword, Me, in the message box, and the messages sent by the other Users will appear starting
with their User names.

How Does It Work?

Liferay Chat portlet (AJAX Instant Messaging) allows Users to automatically chat over XMPP (Jabber) protocol with other Users. Instant Messaging lets members interact with other members in real time. A private room may exists for customers which could give them access to others.

Liferay Chat portlet integrates with a Jabber server, that is, OpenFire. This session will introduce Instant Messaging, AJAX, and Jabber (OpenFire).

OpenFire (previously known as Wildfire Server) is a real-time collaboration (RTC) server, adopted open protocol for instant messaging, XMPP (also called Jabber). URL: http://www.jivesoftware.com/products/openfire/.

Use Instant Messaging

Instant messaging (IM) acts as a form of real-time communication among Users, based on typed text. It allows easy collaboration. In contrast to email, the participants know whether the peer is available. Conversations by instant messaging can be saved for later reference.

One of the Instant Messaging protocols is Extensible Messaging and Presence Protocol (XMPP).

XMPP is an open, XML-inspired protocol for near-real-time, extensible instant messaging (IM) and presence information. It is the core protocol of the Jabber Instant Messaging and Presence technology. URL:http://www.xmpp.org/.

On the one hand, XMPP is based on open standards, different from other instant messaging protocols. Similar to email, XMPP is an open system where a User having a domain name and a suitable Internet connection can run a Jabber server, and talk to others on other servers.

On the other hand, another useful feature of the XMPP system is, transports, also called gateways. Through this, Users can access networks using other protocols. These protocols can be other instant messaging protocols, such as SMS or Email. The case is different from multi-protocol clients, as Users can access XMPP server at the server level. That is, it communicates with other servers through gateway services, which are running on a remote server.

Another interesting feature of XMPP is the HTTP binding behind restricted fi rewalls. For instance, Community A User wants to chat with Community B User.

Community A User and Community B User have accounts on the Jabber Server and the Third Part Server respectively. When Community A User types in and sends his/her message, a sequence of events is set in action, as shown in the following figure:

  • Community A User’s client sends his/her message to the Jabber Server. If Third Part Server is blocked on Jabber Server, the message is dropped.
  • The Jabber Server opens a connection to the Third Part Server. The Jabber server delivers the message to Community B User.
  • If Jabber Server is blocked on Third Part Server, the message is dropped.
  • If Community B User is not currently connected, the message is stored for later delivery.

Jabber is the Linux of instant messaging—an open, secure, ad-free alternative to consumer IM services. URL: http://www.jabber.org/

Employ AJAX

AJAX is Asynchronous JavaScript and XML. In short, AJAX makes portal Pages feel more responsive, by exchanging minimum amounts of data with the server. Thus, the entire portal Page does not have to be reloaded, when the User requests a change. You can use AJAX to increase the portal Page’s interactivity, usability, functionality and speed.

In other words, AJAX acts as an asynchronous data transfer mechanism, that is, HTTP requests, between the browser and the portal server, allowing portal Pages to request a few bits of information from the server, instead of whole portal Pages. The AJAX makes portal applications smaller, faster and more user-friendly as shown in the following figure:

liferay-7In general, AJAX is based on the following standards:

  • JavaS cript—Scripting language of the Web
  • XML—Extensible Markup Language
  • XHTML (or HTML)—Extensible Hypertext Markup Language
  • CSS—Cascading Style Sheets

AJAX follows web standards supported by all major browsers. Thus, AJAX applications are browser and platform independent. The main advantage of AJAX is the separation of data, format, style, and function.

Using Chat Portlet Effectively

The Chat portlet allows Users to chat over XMPP protocol with other logged-in Users automatically. In order to use the Chat portlet effectively, let’s set up an XMPP server and configure Liferay.

Set up XMPP Server

First, we have to set up a XMPP (Jabber) server. Suppose that we use OpenFire as an XMPP (Jabber) server. Here are the steps to set up OpenFire as follows:

  1. Create a folder, and name it OpenFire.
  2. Download the OpenFire.
  3. Extract the fi le to the OpenFire folder.
  4. Open the OpenFire folder and furthermore, bin.
  5. Click on openfire_x_x_x.exe or unzip openfire_x_x_x.tar.gz.
  6. Click Launch Admin.
  7. Proceed with configuring OpenFire based on your requirements, as shown in the following figure.

    liferay-8

Configure Liferay

Then, you need to configure the XMPP server (such as OpenFire) with Liferay. You can simply open portal-ext.properties at $LIFERAY_ROOT/webapps/Root/WEBINF/classes.

You just enter the following lines (Suppose that OpenFire and Liferay are on the same server):

jabber.xmpp.server.enabled=true

reverse.ajax.enabled=true

If you want to configure the integration by default settings, here are some options.
The following is the complete set of properties related to the setup of XMPP server.
[code]
jabber.xmpp.server.enabled=false

jabber.xmpp.server.address=localhost

jabber.xmpp.server.name=localhost

jabber.xmpp.server.port=5222

jabber.xmpp.user.password=admin
[/code]
You can also configure the Chat portlet when XMPP server is on a separate server.
The following lines are a real example.
[code]
jabber.xmpp.server.enabled=true

reverse.ajax.enabled=true

jabber.xmpp.server.address=liferay.cignex.com

jabber.xmpp.server.name=liferay-cignex

jabber.xmpp.server.port=5222

jabber.xmpp.user.password=admin
[/code]
Note that you have to turn firewall off in Windows for the Chat Portlet to run properly.

Working with Mail Portlet

In order to let employees manage their emails, we can use the Liferay Mail portlet. As an administrator of “Palm Tree Publications”, you need to create a Page called “Mail” under the Page, “Community” at the Book Lovers Community Public Pages and also add the Mail portlet in the Page, “Mail”.

Experiencing Mail Management

First of all, login as “Palm Tree”. Then, let’s do the above as follows:

  1. Add a Page called “Mail” under the Page “Community” at the Book Lovers Community Public Pages, if the Page is not already present.
  2. If the Mail portlet is not already present, add it in the Page, “Mail” of the Book Lovers Community where you want to manage mails. You will see the Mail portlet as shown in the following figure.

    liferay-9

Let’s assume that we set up the mail domain as “cignex.com” in the Enterprise Admin portlet for testing purposes, as we have a mail engine with this mail domain already. Of course, you could set up the mail domain as “book.com”, or something else, if you had a mail engine with this mail domain in your hand.

As an edit or of the editorial department, “Lotti Stein”, you may want to manage your mails in the mail domain, “cignex.com”. You can first choose a user name for your personal company the email address, say “admin1234” and register. Let’s do it as follows:

  1. Login as “Lotti Stein”.
  2. Go to the Page “Mail” under the Page, “Community”, at the Book Lovers
    community Public Pages.
  3. Locate the Mail portlet.
  4. Input the value for User name as “admin1234”.
  5. Click the Register button.

Your new email address is “admin1234@cignex.com”. This email address will also serve as your login, as shown in the following figure.

liferay-10You can now check for new messages in your inbox, by clicking the Inbox link first. Then, you can view the Unread messages, and either Check Mail or create a New mail, as shown in the following figure:

liferay-11You can go to the Page of Mail management by clicking on any link of Unread Messages, or Check Mail button or New button. Further, you can manage emails through the Mail portlet of your current account. Email management includes the following features (as shown in the following figure):

  • Create a New email.
  • Check Mail.
  • Reply to an email.
  • Reply All emails.
  • Forward emails.
  • Delete emails.
  • Print emails, and
  • Search.

liferay-12Note that the first email with the subject, “Users in Staging server”, is sent through the SMS Text Messenger portlet. For more details, refer to the forthcoming section.

How to Set up Mail Server?

In order to make the Mail portlet work, we have to set up a mail server with IMAP, POP and SMTP protocols. Suppose that the Enterprise “Palm Tree Publications” has a mail server with the domain “exg3.exghost.com”, an account “admin@cignex.com/
admin1234”, and protocol IMAP, POP and SMTP. As an administrator, you need to integrate this mail server with IMAP, POP and SMTP protocol in Liferay. Let’s do it as follows:

  1. Find the file ROOT.xml in $TOMCAT_DIR/conf/Catalina/localhost.
  2. Find the mail configuration first.
  3. Then configure it as follows:
    [code lang=”xml”]
    <! — Mail –>

    < Resource

    name="mail/MailSession"

    auth="Container"

    type="javax.mail.Session"

    mail.imap.host="exg3.exghost.com"

    mail.imap.port="143"

    mail.pop.host="exg3.exghost.com"

    mail.pop.port="110"

    mail.store.protocol="imap"

    mail.transport.protocol="smtp"

    mail.smtp.host="exg3.exghost.com"

    mail.smtp.port="2525"

    mail.smtp.auth="true"

    mail.smtp.starttls.enable="true"

    mail.smtp.user="admin@cignex.com"

    password="admin1234"

    mail.smtp.socketFactory.class="javax.net.ssl.SSLSocketFactory"

    >
    [/code]

In short, a Mail portlet is an AJAX web-mail client. We can configure it to work with any mail server. It reduces page refreshes, since it displays message previews and message lists in a dual pane window.

How to Set up Mail Portlet?

If you have proper Permissions, you can change the preferences of the Mail portlet. To change the preferences, you can simply click the Preferences icon to the upper right of the Mail portlet.

With the Recipients tab selected, you can find potential recipients from the Directory (Enabled or Disabled) and the Organization (My Organization or All Available).

Click the Save button after making any changes.

Using the Filters tab, you can set the values to filter emails associated with an email address to a Folder. Click the Save button after making any changes.

Note that the maximum number of email addresses is ten. This number is also configurable at the portal-ext.properties

Similarly, the Forward Address tab allows all emails to be forwarded to the email address you want. Enter one email address Per Line. Remove all entries to disable email forwarding. Select Yes to leave, or No to not leave a copy of the forwarded message. Click the Save button after making any changes.

Further, the Signature tab also allows you to set up your signature using HTML text editor. The signature you have set up will be added to each outgoing message. Click the Save button after making any changes.

The Vacation Message tab allows you to set up vacation messages using HTML text editor. The vacation message notifies others of your absence (as shown in the following figure). Click the Save button after making any changes.

liferay-13

Using Permissions

The following table shows Permissions for the Mail portlet. A Community User can set up all Permissions (marked ‘X’) while a Guest User has the View, Configuration and Preferences Permissions. By default, a Community (marked ‘*’) as well as a Guest User has View action.

ViewViews this portletX, *X, *ConfigurationConfigures Permissions of this portletXXPreferencesConfigures mail setting of this portletXX

Action Description Community Guest

Obviously, as a User of the Book Lovers Community, “Lotti Stein” has only View Permissions on the Mail portlet, by default. Since the Book Lovers community has no Permission “Preferences”, it follows that “Lotti Stein” too has no “Preferences” Permission.

As an administrator, you may need to set up the Community Users having Permissions, Preference as well as View, on the Mail portlet. Thus, the Community User can set up mail settings. That is, you need to add Permissions (Preference) on the Mail portlet at the Book Lovers community. Let’s do it as follows (see the following figure):

  1. Click on the Configuration icon to the top right of the Mail portlet.
  2. Then click on the Permissions tab.
  3. Select the Community tab.
  4. Select Permission, Preferences, in the Available box.
  5. Click on the Add arrow, and
  6. Click on the Save button if you are ready.

    liferay-14

Using Mail Portlet effectively

Liferay Portal can integrate with Washington IMAP + Sendmail, Cyrus IMAP + Postfix, and Dovecot + Postfix, as well as with Microsoft Exchange and other IMAP servers. As stated above, the mail server ” exg3.exghost.com” is Microsoft Exchange server.

You can access your email through an IMAP server. If access is on IMAP, the portal does not have to know where to persist the mail.

IMAP stands for Internet Message Access Protocol. URL:http://www.imap.org/.

One of the popular protocols used for email is IMAP, an application layer Internet protocol. IMAP operates on port 143 that allows a local client to access email on a remote server.

IMAP supports both connected and disconnected modes of operation. Until the User explicitly deletes them, email IMAP clients generally leave messages on the server. Moreover, IMAP offers access to the mail store.

IMAP has a lot of advantages. Here, we have listed just some of them:

  • Use connected and disconnected modes of operation.
  • Users can connect to the same mailbox simultaneously.
  • Users have access to MIME message parts and partial fetch.
  • Has message state information.
  • Supports multiple mailboxes on the server.
  • Provides ability for search on the server-side.
  • Has a built-in extension mechanism.

Working with SMS Text Messenger

In order to let employees send text message to others, anytime, we can use the Liferay SMS Text Messenger portlet. As an administrator of “Palm Tree Publications”, you need to create a Page called “SMS” under the Page “Community” at the Book Lovers Community and add the SMS Text Messenger portlet in the Page, “SMS”.

Using SMS Text Messenger

First of all, login as “Palm Tree”. Then, let’s do the above action as follows:

  1. Add a Page called “SMS” under the Page “Community” at the Book Lovers Community Public Pages, if the Page is not already present.
  2. Add the SMS Text Messenger portlet in the Page, “SMS” of the Book Lovers Community where you want to set up SMS Text Messenger (if this portlet is not already present). You will see the SMS Text Messenger portlet as shown in the following figure:

    liferay-15

As an editor of the editorial department, “Lotti Stein” wants to send a Message, say “Users in Staging server”, to a person, say”admin@cignex.com”. Let’s do it as follows:

  1. Login as “Lotti Stein”.
  2. Go to the Page “SMS” under the Page “Community” at the Book Lovers community Public Page.
  3. Locate the SMS Text Messenger.
  4. Input value for To as “admin@cignex.com”, Subject as “Users in Staging server” and a Message.
  5. Click the Send Text Message button.

The User “admin@cignex.com” will receive this email sooner or later, as we have described in the previous section.

liferay-16

How to Set up SMTP?

In order to make SMS Text Messenger work well, we have to set up the mail server with SMTP protocol. Suppose that the Enterprise “Palm Tree Publications” has a mail server with a domain “smtp.gmail.com”, an account “jonasxyuan/jonas1234”, and a protocol, SMTP. As an administrator, you need to integrate this mail server with SMTP protocol in Liferay. Let’s do it as follows:

  1. Find the file ROOT.xml in $TOMCAT_DIR/conf/Catalina/localhost.
  2. Find the mail configuration first.
  3. Then, configure it as follows:
    [code]
    < Resource

    name="mail/MailSession"

    auth="Container"

    type="javax.mail.Session"

    mail.imap.host="smtp.gmail.com"

    mail.pop.host="smtp.gmail.com"

    mail.store.protocol="imap"

    mail.transport.protocol="smtp"

    mail.smtp.host="smtp.gmail.com"

    mail.smtp.port="465"

    mail.smtp.auth="true"

    mail.smtp.starttls.enable="true"

    mail.smtp.user="jonasxyuan"

    password="jonas123456"

    mail.smtp.socketFactory.class="javax.net.ssl.SSLSocketFactory"

    >[/code]

In short, the SMS Text Messenger portlet allows you to send SMS text messages from your portal page anytime.

Using SMS Effectively

The Short Message Service (SMS), called text messaging, is used to send short messages to and from mobile phones. It provides a mechanism for the delivery of short text messages over mobile networks, in order to transmit messages to and from mobiles. The text message from the sender can be stored in a central short message center, which then forwards it to the recipient. If the recipient is not available, the short message is stored temporally and will be sent later. SMS provides return receipts. Thus, the sender gets a brief message notifi cation if the short message is delivered to the recipient.

You may need to read the following part, if you are interested in the organization of network elements for supporting SMS. Otherwise, you can leave it for your future needs. The following fi gure shows a typical organization of network elements in a network supporting SMS (refer to more details at http://www.wirelessdevnet.com/channels/sms/features/sms.html).

liferay-17The SMC (Short Message Center) stores and forwards messages, to and from the message station. The SME (Short Message Entity) receives and sends short messages.

The SMS GWMS (SMS gateway MSC), a gateway MSC, can receive short messages. After receiving the short message from the message center, GMSC employs the SS7 (Signaling System #7) network to interrogate the current position of the mobile station from the HLR (home location register).

HLR, as a main database, holds information about the subscription profi le of the mobile. It also maintains the routing information for the subscriber where the mobile is currently situated. The GMSC thus passes on the short message to the correct MSC.

MSC (Mobile Switching Center) switches connections between mobile stations.

A VLR (Visitor Location Register) communicates with each MSC and contains temporary information about the mobile. MSC switches the short message to the corresponding BSS (Base Station System), which transmits the short message to the mobile. The BSS is made up of transceivers, which send and receive information over the air interface, to and from the mobile station. The short message is passed over signaling channels, so that the recipient (for example, mobile) can receive this short piece of information, even if a data call or a voice call is going on.

Summary

This chapter discussed how to add a participant for chatting, how to manage (view and delete) participants in the Chat portlet, how to start chatting, and how to set up the Chat portlet fi rst. Then it discussed how to manage (check, delete, add, reply, forward, search) emails and also to set up the Mail portlet properly. Finally, it discussed how to manage the SMS Text Messenger portlet and send SMS
text messages.

Filed Under: Liferay Portal Tagged With: Liferay Portal

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

What is new in Java 6.0 Collections API?

The Java 6.0 Compiler API

Copyright © by JavaBeat · All rights reserved