Blog Post

...

Liferay Spring MVC Portlet (+JPA, Maven) part.2

In previous post Liferay Spring MVC Portlet (+JPA, Maven) part.1 I wrote how to develop a Liferay Spring Portlet using Maven, in this article I’ll discuss how to inject the JPA ORM in it.

First of all we need to include Spring and JPA Maven dependencies:

<!-- Spring -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>x.x.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>x.x.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>x.x.RELEASE</version>
</dependency>       
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc-portlet</artifactId>
    <version>x.x.RELEASE</version>
</dependency>
<!-- JPA -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.6.8.Final</version>
</dependency>   

Usually database connection information is kept in portal-setup-wizard.properties located in Liferay installation directory (in case when connection properties are set at first Liferay start via GUI) or in user defined extension of Liferay properties file located in /ROOT/WEB-INF/classes/portlet-ext.xml:

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

To extract this connection information and plug it into dataSource property of JPA entityManagerFactory there is getDataSource() of com.liferay.portal.kernel.util.InfrastructureUtil method should be used: 

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="dataSource" class="com.liferay.portal.kernel.util.InfrastructureUtil" factory-method="getDataSource" />
</beans>

In order to create JPA javax.persistence.EntityManagerFactory we will use standard Spring Factory Bean LocalContainerEntityManagerFactoryBean. In this way we set up in spring context the EntityManagerFactory that can be easily shared in DAO by means of dependency injection. For this bean we also must set packagesToScan property which defines a path to scan for JPA entity classes instead of using a standard persistence.xml file. By this approach we can omit persistence.xml that makes our life easier. One more property jpaVendorAdapter required to specify database type and some other not so important options. The final look of EntityManagerFactory is the following:

    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" >
            <list>
                <value>com.somepackage</value>
            </list>
        </property>
        <property name="jpaVendorAdapter">
            <!-- Mysql  -->
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
                  p:database="MYSQL"
                  p:showSql="false"
                  p:databasePlatform="org.hibernate.dialect.MySQLDialect"
                  p:generateDdl="true"/>
        </property>
    </bean>

In current application we also want to use Spring transactions for defined entityManagerFactory bean, this can be done with the including of the following tags to the spring context:

    <!-- Add Transaction support -->
    <bean id="txManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <!-- Use @Transaction annotations for managing transactions -->
    <tx:annotation-driven transaction-manager="txManager"/>

Now we are done with spring configuration and can go further – to JPA entities implementation. Let’s imagine that we need to have a database entity that reflects some abstract business “Issue”:

package com.somepackage.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "issue")
public class Issue {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long issueId;
    
    @Column(name = "name")
    private String name;
}

And DAO class for current entity will look:

package com.somepackage.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.somepackage.model.Issue;

@Repository
@Transactional
public class IssuesDAO {

    @PersistenceContext
    private EntityManager em;

    public void createIssue(Issue entity) {
        em.persist(entity);
    }

    public void updateIssue(Issue entity) {
        em.merge(entity);
    }

    public void deleteIssue(long issueId) {
        Issue is = getIssueById(issueId);
        if (is != null) {
            em.remove(is);
        }
    }

    @Transactional(readOnly = true)
    public Issue getIssueById(long issueId) {
        return em.find(Issue.class, issueId);
    }
}

That’s all. At this point we get a complete Liferay Spring MVC Portlet that uses JPA. Thank you for your attention!

Comments (1)

Tags: liferay


Comments:

...

luis Jan 13, 2016 at 21:16 #

¿Puedes compartir tus fuentes o en todo caso las versiones de Spring y JPA empleadas?

Leave a Comment