Showing posts with label service builder. Show all posts
Showing posts with label service builder. Show all posts

Friday, January 24, 2014

Liferay Service Builder Underlying Concept

Objective

Provide full detailed information about Liferay Service Builder Underlying Concept.

What is Liferay Service Builder?

Liferay service builder is a tool which will generate the service layer to Plugin portlets. By using this service layer we can interact with database and perform data base CRUD operations.
Service builder tool is reduce the developer effort when they develop the service layer to portlet.

What is service layer?

Service layer is set of java classes and interfaces which implement the database interaction logic.

Data base interaction is like connecting to database, insert data, delete data and update data in database tables.

When we implement any service classes or database interaction logic to portlet we may need to write same kind of code in many portlets i.e. data base interaction CRUD operations.

To avoid this same effort for each portlet, service builder tool will generate the all common data base interaction classes and interfaces so that we can reduce developer effort and we simple use generated classes to perform the database interactions.

How does Service Builder Tool implement the service layer?

Service Builder uses the spring and hibernate integration Data Access Objects implementation mechanism in short we can call it as DAO implementation.

Here Service Builder Tool will use the spring and hibernate technology to develop service layer to Plugin portlet.

Main Artifacts in Service Layer
  1. Persistence/DAO classes
  2. Model/POJO
  3. Service Classes

Persistence/DAO classes:

Persistence/DAO classes will provide the direct data base interaction like insert, delete and update the data in table. such kind of logic will be present in this classes.

Conceptually for each table we have one persistence class that will interact with table. Here actual data base interaction code will be present.

As we know that to interact with database we need hibernate/jdbc in java. Persistence/DAO classes we will get the session factory object and from that we will open session, with that session object we will do all database interactions, once we finish all tasks we will close the session.

Model/POJO

The model or POJO classes will used to pass the data from application layer to database. In the ORM/Hibernate context each row in tables is one model or POJO object. This row we will represent as Model/POJO class. This is simple java bean or java class has setters and getters methods.

The session always use this object to pass data to table and same way it get the data from table and fill in pojo/model object.

At the time of database interaction we call this object as Persistence object. The persistence object is java bean it will bind with table’s rows when we open session to respective table.

Service Classes

Service classes will be separate the application layer and direct Data base interaction layer. Before inserting data if any business logic is requires then we will use this service classes 

After perform the business logic then we will call DAO classes to interact with database.
We can use one service class and there we will create many DAO objects to interact with many tables in database.

What are the required things to build service layer?
  1. Data Source
  2. Configure All Model classes in Hibernate mapping files
  3. Session factory
  4. Configure All Service Implementation classes in spring configuration files
  5. Load all configuration files in spring context

Note:

As a developer we need not to do anything which I have spoken above. Conceptually I am giving idea and Service Builder will do all configurations which I specified earlier.

All configuration files can be visible in portlet /WEB-INF/src/META-INF directory

Data Source

Data source will provide the database connection details like drives class, connection URL and user’s credentials to connect to data base.

Example for data source configuration as follows and liferay has its own data source implementation class.

<bean id="liferayDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="liferayDataSourceWrapper" />
</bean>
<bean id="liferayDataSourceImpl" class="com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean">
<property name="propertyPrefix" value="jdbc.default." />
</bean>
<bean id="liferayDataSourceWrapper" class="com.liferay.portal.dao.jdbc.util.DataSourceWrapper">
<constructor-arg ref="liferayDataSourceImpl" />
</bean>

In above configuration we can see property prefix jdbc.default for data source .database configuration properties should start with jdbc.default. 

If we want change database connection details we need to configure these details in portal-ext.proprties file and this file should be places in Liferay Home directory

The following example for data source configuration for MySQL database in portal-ext.proprties file

jdbc.default.driverClassName=com.mysql.jdbc.Driver
 jdbc.default.url=jdbc:mysql://localhost:3306/lportal?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
 jdbc.default.username=root
 jdbc.default.password=

Note:

This configuration you can see in the following location in liferay portal and data source common for all portlets in liferay until we configure new data source for portlet.


/portal-impl/src/META-INF/infrastructure-spring.xml


Note:

 For entire liferay portal will use default data source and as soon as we start the liferay portal then the data source will be ready, this data source we can use in any portlet. We can also define new data source in portlet when ever need to connect to another database.

Configure All Model classes in Hibernate mapping files

Hibernate mapping file is responsible to mapping model/pojo classes with respective data base tables.

Session factory uses this file and it loads all model/pojo classes’ objects in session factory and it will give to the session when the respective session is opened for database tables.
In liferay we have two kinds of session factories
  1. Portal Session Factory
  2. Portlet Session Factory

Portal Session Factory

Portal Session Factory is responsible for load all portal related model/pojo objects. When we open session using portal session factory then it can interact with all tables which are in portal level.

We can see the available portal level tables and its model classes in the portal-hbm.xml file. Portal session factory read this xml file and load all model object.

The following is portal level session factory configuration

<bean id="liferayHibernateSessionFactory" class="com.liferay.portal.spring.hibernate.PortalHibernateConfiguration">
<property name="dataSource" ref="liferayDataSource" />
</bean>
<bean id="liferaySessionFactory" class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl">
<property name="sessionFactoryClassLoader">
<bean class="com.liferay.portal.kernel.util.PortalClassLoaderUtil" factory-method="getClassLoader" />
</property>
<property name="sessionFactoryImplementor" ref="liferayHibernateSessionFactory" />
</bean>

Note:

You can see the liferay session factory configuration in the following location


/portal-impl/src/META-INF/hibernate-spring.xml


You can see all portal level model classes and it’s mappings in portal-hbm.xml in the following location


/portal-impl/src/META-INF/portal-hbm.xml


Portlet Session Factory:

Portlet session factory is individual to each Plugin portlet. This session factory configuration done within portlet configuration files i.e. hibernate-spring.xml this file we can see in portlet WEB-INF/src/META-INF directory.

Session factory get Model/POJO classes information from portlet-hbm.xml files. Portlet Session Factory is responsible to load all model objects which are related to portlet level. 

When we open session from portlet session factory then the session can interact with only the tables which are related to portlet.

The following is session factory configuration for portlet

<bean id="liferayHibernateSessionFactory" class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil" factory-method="newBean">
<constructor-arg value="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration" />
<constructor-arg>
<map><entry key="dataSource" value-ref="liferayDataSource" /></map>
</constructor-arg>
</bean>
<bean id="liferaySessionFactory" class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil"
factory-method="newBean"><constructor-arg
value="com.liferay.portal.dao.orm.hibernate.PortletSessionFactoryImpl" />
<constructor-arg>
<map>
<entry key="dataSource" value-ref="liferayDataSource" />
<entry key="sessionFactoryClassLoader" value-ref="portletClassLoader" />
<entry key="sessionFactoryImplementor" value-ref="liferayHibernateSessionFactory" />
</map>
</constructor-arg>
</bean>

Note:

When we interact with Portal level database table in Plugin portlet we will get some kind of challenges.

The following is link which will explain the all possible challenges and it solutions


 Configure All Service Implementation classes in spring configuration files

Now we need to configure all DAO and Service classes in spring configuration files so that it will ready to use when portlet context is ready.

To do this we need to configure all service classes in spring-portlet.xml file which is available in portlet WEB-INF/src/META-INF directory

The following is example bean configuration for portlet services


<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            default-destroy-method="destroy" default-init-method="afterPropertiesSet"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="com.meera.db.service.StudentLocalService" class="com.meera.db.service.impl.StudentLocalServiceImpl" />
<bean id="com.meera.db.service.StudentService" class="com.meera.db.service.impl.StudentServiceImpl" />
<bean id="com.meera.db.service.persistence.StudentPersistence"
class="com.meera.db.service.persistence.StudentPersistenceImpl" parent="basePersistence" />
<bean id="com.meera.db.service.persistence.StudentFinder" class="com.meera.db.service.persistence.StudentFinderImpl" parent="basePersistence" />
</beans>

What is happening when we run service builder for portlet?

When we run service builder in liferay portlet, it will create all hibernate and spring configuration files and data base service interaction java classes and interfaces.

The following are main things and it will generate after we run service builder

service directory (docroot\WEB-INF\service):

This is directory for service layer related interface and java classes will be created here
The following is example screen to show service directory.


sql directory (docroot\WEB-INF\sql):

Service builder create the sql directory and places the all required sql script for portlet i.e table creation scripts, indexes scripts.

The following is example screen for sql directory and portlet sql scripts.


service jar file:

All service classes and interfaces will be packaged in service jar file and the name of jar file like portlaName-service.jar file this jar file will be places in portlet lib directory. This jar is help us when we want share portlet services in other portlet contexts.

The following is screen to show portlet service jar file in lib directory



All implementation classes will be generated in portlet src directory.

The following daigram shows model implementation classes in src directory of portlet.


The following screen showed service implementation and Persistence Implementation directories and there we can see all implementation classes


All spring and hibernate configuration created in WEB-INF\src\META-INF

The following screen shows spring and hibernate configuration files for portlet.


service.properties file

This file is especially for provide some configurations to services and it will be created in portlet WEB-INF\src directory. Some of the properties are used to control service layer.

The following screen to show service.properties file in portlet


           
How does portlet service layer is working?
  • When we run service build then service builder will be create all java classes and required xml configurations.
  • In xml configuration are like session factory, data source and all service layer implementation beans registration in hibernate and spring configuration files.
  • As soon as we deploy the portlet then all configurations will be loaded by spring context. Then spring context is responsible for load session factory, data source and other serve implementation classes.
  • Spring will use Inversion of control to create objects and make it available to application or portlet.
  • Now portlet can interact with database by using service objects because its already available to use.
  • As developer we need to get services from service Util classes and model classes to interact with database.
  • We have many methods in Util classes we can use those methods to perform database operations.

Note:

This is conceptual understanding about service builder and I will show example portlet in next coming post.

Author

Wednesday, January 22, 2014

Liferay Service Builder Tags Detail Part-1

Objective:

Provide detailed information about service builder root level tags and usage.

Liferay service builder is tool to generate service layer to Plugin portlets. With minimal effort developer can develop service layer to portlet.

Liferay service builder generate many java service classes and Util classes from these classes we can do most of the curd operations.

How we will use service builder in Liferay Portlets?
  • To use service builder tool in portlet we need to define service.xml file in portlet WEB-INF directory.
  • Service builder will use certain predefined tags so that we have to define those tags in service.xml file
  • All tags information will be available in liferay-service-builde_X_x.dtd file. Liferay have different versions of DTD files.
  • Once we define everything in service.xml we need run ant build-service target form eclipse or command prompt
  • Once we run ant target then all required service classes will be generated so that we can use these classes in portlet.

Assumption:

Assume we want create service builder to Student Entity so that we will generate many service classes and Util classes which will use to interact with data Student tables in data base

Example for define Entity in service.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.meera.sb">
<author>E5410</author>
<namespace>SB</namespace>
<entity name="Student" local-service="true" remote-service="true" >
<!—Define columns tags -->
<!—Define finder tags -->
<!—Definde order tags -->
</service-builder>

Note:

Whenever we use service builder we need to specify the service builder DTD file in DOCTYPE tag so that it will use the tags those defined in dtd file. This is very important when we use service builder tool.

The following are service builder tags and its attribute details

Service builder have following important root level tags

service-builder
author
namespace
entity
service-builder-import

service-builder

The parent tag in service.xml file is service-builder all tags which are related to service builder should enclosed by parent tag.

Attributes for service-builder tag:

packeage-path:  

This is specifying that where all service builder generated classes will be placed in given package path

Example:

<service-builder package-path="com.meera.sb">
<!—Define Enities tags -->
</service-builder>

In above all service builder generated classes will be places in com.meera.sb base package.

author

This specify the author who is developing this service builder

namespace

Name space tag will used to avoid the name collegians between data base tables.
Assume some time we may have scenario tow portlet have same table name but columns are different.

If we don’t want use name space then existed tables override by another portlet table columns.

To avoid this we will use name space so that we can use same table in many portlets so that table name will be appended with name space

Example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.meera.sb">
<author>E5410</author>
<namespace>SB</namespace>
<entity name="Student" local-service="true" remote-service="true" >
<!—Define columns tags -->
<!—Define finder tags -->
<!—Definde order tags -->
</service-builder>

Database Table Name= Name Space Tag Value + Entity Name
For above definition the Table Name will be SB_Student

Note:

To avoid Name space append to entity name we need to use table attribute in

enitity

Entity tag used to define the service layer entity class.  For each physical table we need entity definition in service.xml so that we can do data base operation on that table.
All entities are enclosed by <service-builder/> parent tag

Example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.meera.sb">
<author>E5410</author>
<namespace>SB</namespace>
<entity>
-----
-----
</entity>
<entity>
-----
-----
</entity>

<entity>
-----
-----
</entity>
</service-builder>

Important Attributes for entity tag:


name             
table
local-service
remote-service
data-source
session-factory
tx-manager
cache-enabled
json-enabled


Name:

This specifies the name of the entity so that all service classes and model classes’ names will start with entity name.

Possible attribute values:

 Any String Value we can use as value better don’t use some special characters

Note:

This is mandatory attribute

Example:


<entity name="Student">
----
-----
</entity>


table:

This specifies the name of the table in data base. Means the service layer service will do data base operations for given table.

Possible attribute values:

This is name of table in data base nothing but string value

Note:

This is optional attribute

Example:


<entity table="Student">
----
-----
</entity>


Assume already table is existed in data bases for this we want use the service builder service then we have to table attribute in entity tag.

local-service:

This is Boolean value and this will generate the all service classes those we can use in local or within same application environment and the default value is false.

Possible attribute values:

It table Boolean values possible values can be true/false

Note:

This is optional attribute

Example:


<entity local-service="true/flase">
----
-----
</entity>


remote-service:

When we want generate web service to the entity then we will use this attribute. The default value is false. This will generate SOAP and JSON REST web service to entity. When we want expose our data to other platforms as web service then we have to use this attribute.

Possible attribute values:

It table Boolean values possible values can be true/false

Note:

This is optional attribute

Example:


<entity remote-service="true/flase">
----
-----
</entity>


data-source:

Liferay have given flexibility to define custom data sources for portlet so that we can specify the custom data source through this attribute.
This tells us in which data source our data base table is available. Default it will use liferay data source that is lportal data base to create table or access table.

Possible attribute values:

Name of the data source we configures for portlet.

Note:

This is optional attribute

Example:


<entity data-source="mydatasource">
----
-----
</entity>


For More information please go through following links:


session-factory:

This also similar to data source we can use custom session factory. When we want define our own session factory so that we can specify using this attribute so that persistence class loaded in specified session factory.

Possible attribute values:

Name of the session factory we configures for portlet.

Note:

This is optional attribute

Example:


<entity session-factory="mysessionfactory">
----
-----
</entity>


For More information please go through following links:


tx-manager:

This attribute specify that the entity/table whether use the transactions or not.

Possible attribute values:

 Name of transaction manager configured for portlet/none

If we use none value it won’t use transaction manager and by default every entity use the        liferay transaction manager specify in spring configuration files.

Note:

This is option attribute

Example:


<entity tx-manager="none/mytxmaneger">
----
-----
</entity>


cache-enabled:

When want handle cache mechanism on entity then we have to use this attribute
Possible attribute values:

It will take true/false values.

This is option attribute and by default for all entities cache is implemented by service builder if we don’t want then we need to make it false value. Set the value to false if data in the table will be updated by other programs.

Note:

This is option attribute

Example:


<entity cache-enabled="true/flase">
----
-----
</entity>


json-enabled :

The json-enabled value specifies whether or not the entity should be annotated
for JSON serialization. By default, if the remote-service value is true, then
The json-enabled value is true.

Example:


<entity json-enabled="true/flase">
----
-----
</entity>


service-builder-import:
The service-builder-import allows you to split up a large Service Builder file
into smaller files by aggregating the smaller Service Builder into one file.
Note that there can be at most one author element among all the files. There can
Also only be one and only one namespace element among all the files.

Important Attribute for service-builder-import tag

file

The attribute file is interpreted as relative to the file that is importing it.


  
Example


<service-builder-import file=”service.1xml”>


Note:

Some of the root tags have its child tags so I will post remaining child tags information on second part of the article

The following is sample example for service.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.meera.db">
<author>E5410</author>
<namespace>meera</namespace>
<entity name="Student" local-service="true" remote-service="true" cache-enabled="true">
<!-- PK fields -->
<column name="studentId" type="long" primary="true" />
<!-- Audit fields -->
<column name="studentName" type="String" />
<column name="studentPlace" type="String" />
<column name="studentCollege" type="String" />
<!-- Order -->
<order by="asc">
<order-column name="studentId" />
</order>
<!-- Finder methods -->
<finder name="studentPlace" return-type="Collection">
<finder-column name="studentPlace" />
</finder>
</entity>
<entity name="Course" local-service="true" remote-service="true" cache-enabled="false">
<column name="courseId" type="long" primary="true" />
<!-- Audit fields -->
<column name="courseName" type="String" />
<column name="courseGroup" type="String" />
<!-- Order -->
<order by="asc">
<order-column name="courseId" />
</order>
<!-- Finder methods -->
<finder name="courseGroup" return-type="Collection">
<finder-column name="courseGroup" />
</finder>
</entity>
</service-builder>

Reference Links:


Author

Recent Posts

Recent Posts Widget

Popular Posts