希望在liferay中用portlet的方式实现配置多个数据源做数据展现,先参考来自官网论坛的例子配置数据源:做了一个training的例子;
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Extending%20Liferay%20Tables%20in%20Another%20Database/pop_up
1,root.xml
ROOT.XML
Now, we can proceed to the real stuff. So we need to add the another jdbc resource to tomcat. We add that in CATALINA_HOME/conf/Catalina/localhost/ROOT.xml another Resource.
<!-- MySQL -->
<Resource
name="jdbc/LiferayPool"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8"
username="root"
password=""
maxActive="20"
/>
<Resource
name="jdbc/TrainingPool"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/training?useUnicode=true&characterEncoding=UTF-8"
username="root"
password=""
maxActive="20"
/>
Main | Proposals FrontPage | 最近变动 | 所有页 | 断连结页
Extending Liferay Tables in Another Database
标记: development liferay v5.1
Table of Contents [-+]
1 Introduction
2 Preparation
3 ROOT.XML
4 service.xml
5 ext-data-source-spring.xml
6 portal-ext.properties
7 Let's build
8 Create database and table
9 Testing from existing portlet
10 Troubleshooting
11 See Also
Introduction
This article is based on Liferay 5.0.1 and Tomcat 6 bundle. Ext environment is 5.0.1, except all build.xml files are from trunk (5.0.2), as there were some minor failures with build files in 5.0.1. There are some differences between old and this new version of Liferay and Ext environment so I wanted to have the procedure written. Considering that sometimes community is not very fast and elaborative on answers this article might save you some time.
Preparation
These installs can be anywere therefore I use aliases to keep it relative.
Liferay–Tomcat bundle is installed in folder e.g. liferay-portal-tomcat-6.0-5.0.1. which I will refer to as CATALINA_HOME.
Ext environment is installed in folder e.g. liferay-portal-ext-5.0.1 which I will refer to as EXT_ENV.
Liferay source 5.0.1 is located in e.g. liferay-portal-src-5.0.1 which I will refer to as LIFERAY_SOURCE.
Few other notes:
You need to be sure that app.server.Administrator.properties exists in EXT_ENV and that app.server.parent.dir points to CATALINA_HOME. Note: use slashes instead of backslashes.
If EXT_ENV is in directory with spaces and you execute ant from a dos box, use tilda (~) notation to avoid spaces, otherwise build will fail at certain phases. E.g. c:\program files\Ext should be c:\progra~1\ext when working from dos box. Use /x parameter in dir if needed to find out short name. If using eclipse to execute ant, then this might not be relevant.
Example of app.server.Administrator.properties:
app.server.type=tomcat
app.server.parent.dir=C:/liferay-portal-tomcat-6.0-5.0.1
app.server.tomcat.version=6.0
app.server.tomcat.dir=${app.server.parent.dir}
app.server.tomcat.classes.global.dir=${app.server.tomcat.dir}/lib
app.server.tomcat.lib.endorsed.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.lib.global.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.lib.support.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.support.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.zip.name=liferay-portal-tomcat-6.0-${downloads.version.file.name}.zip
ROOT.XML
Now, we can proceed to the real stuff. So we need to add the another jdbc resource to tomcat. We add that in CATALINA_HOME/conf/Catalina/localhost/ROOT.xml another Resource.
<!-- MySQL -->
<Resource
name="jdbc/LiferayPool"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8"
username="root"
password=""
maxActive="20"
/>
<Resource
name="jdbc/TrainingPool"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/training?useUnicode=true&characterEncoding=UTF-8"
username="root"
password=""
maxActive="20"
/>
<!-- Oracle -->
We are done with tomcat and datasource here. Now we can move to the Ext environment.
2,每一个portlet,会对应一个 service.xml
Service xml is located at EXT_ENV/ext-impl and let’s append Training entity at the end before </service-builder>.
<entity name="Training" local-service="true" data-source="trainingDataSource" //在此配置数据源
session-factory="trainingSessionFactory" //配置sessionfactory
tx-manager="trainingTransactionManager">
<!-- PK fields -->
<column name="userId" type="long" primary="true" />
<!-- Other fields -->
<column name="dogName" type="String" />
<column name="wifeName" type="String" />
</entity>
</service-builder>
详细请参加 serviceBuilder 元素解释
As you can see, we have 3 new attributes that we don’t use when we work with lportal database, and they are data-source, session-factory and tx-manager. You can assign these attributes to bean names of your choice, but I would like to follow Liferay naming pattern as above training + TransactionManater, training + SessionFactory, etc.
Now, we need to declare beans that we used in 3 attributes mentioned above . So we meet soon another important config file that we wouldn't have to create if we weren't intend to use a different database.
3,ext-data-source-spring.xml 需要自己重新建立一个xml配置文件,此文件和ext-spring.xml 在同一目录下.
ext-data-source-spring.xml will be created inside EXT_ENV/ext-impl/src/META-INF folder. Actually you can name this file any way you like, but this naming this follows Liferay's pattern.
To keep the life easy, I copied original file from LIFERAY_SOURCE\portal-impl\src\META-INF\data-source-spring.xml and have saved it into EXT_ENV/ext-impl/src/META-INF/ext-data-source-spring.xml
Short explanation of changes - here's original bean:
<bean id="liferayDataSourceTarget" class="com.liferay.util.spring.jndi.PortalDataSourceFactoryBean" lazy-init="true" />
We are not using class PortalDataSourceFactoryBean as it directly points to the liferay datasource. We will use spring’s JndiObjectFactoryBean which takes one argument (property), jndiName, and that’s exactly what we need. Our replacement code is:
<bean id="trainingDataSourceTarget" class="com.liferay.portal.spring.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiName">
<value>jdbc/TrainingPool</value>
</property>
</bean>
Now, 3 other beans were changed, but these were simple changes, just renamed IDs from liferayDataSource, liferaySessionFactory, liferayTransactionManager to trainingDataSource, trainingSessionFactory, trainingTransactionManager. Note that I changed arguments (properties) to our new bean IDs. So the final code is:
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "[http://www.springframework.org/dtd/spring-beans.dtd">]
<!-- Copy from: liferay-portal-src-5.0.1\portal-impl\src\META-INF\data-source-spring.xml, paste here and then modify. -->
manager="trainingTransactionManager"> -->
<beans>
<bean id="trainingDataSourceTarget" class="com.liferay.portal.spring.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiName">
<value>jdbc/TrainingPool</value>
</property>
</bean>
<bean id="trainingDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy" lazy-init="true">
<property name="targetDataSource">
<ref bean="trainingDataSourceTarget" />
</property>
</bean>
<bean id="trainingHibernateSessionFactory" class="com.liferay.portal.spring.hibernate.PortalHibernateConfiguration" lazy-init="true">
<property name="dataSource">
<ref bean="trainingDataSource" />
</property>
</bean>
<bean id="trainingSessionFactory" class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl" lazy-init="true">
<property name="sessionFactoryImplementor">
<ref bean="trainingHibernateSessionFactory" />
</property>
</bean>
<bean id="trainingTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" lazy-init="true">
<property name="dataSource">
<ref bean="trainingDataSource" />
</property>
<property name="sessionFactory">
<ref bean="trainingHibernateSessionFactory" />
</property>
</bean>
</beans>
I hope you remember that jdbc/TrainingPool comes from ROOT.XML. Perhaps you wonder now, how Liferay will know about our newly created ext-data-source-spring.xml file and all beans we did there? Well, it wont - we have to tell Liferay to take our new xml into account.
Hopefully in some future version this ext-data-source-spring.xml might be already included in liferay implementation (vote LEP-6570) and then we might skip the following section, but for now, we have to do changes in portal-ext.properties and add our ext-data-source-spring.xml there, so let's see how.
4,portal-ext.properties 需要在此文件里添加覆盖的配置文件。
This file is located at EXT_ENV/ext-impl/src (and later, after first build-service, at EXT_ENV/ext-impl/classes - always check that they are synchronized, unless you always do annoying ant clean) and we will again do some copy-pasting. So let’s open original file to get some inspiration: LIFERAY_SRC/portal-impl/classes/portal.properties and copy whole spring.configs section:
# MySQL
#
jdbc.default.driverClassName=com.mysql.jdbc.Driver
jdbc.default.url=jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.default.username=root
jdbc.default.password=root
jdbc.default.jndi.name=jdbc/LiferayPool
database.mysql.engine=InnoDB
jdbc.one.driverClassName=com.mysql.jdbc.Driver
jdbc.one.url=jdbc:mysql://localhost/training?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.one.username=root
jdbc.one.password=root
jdbc.one.jndi.name=jdbc/TrainingPool
#database.mysql.engine=InnoDB
spring.configs=\
META-INF/activemq-spring-jms.xml,\
META-INF/data-source-spring.xml,\
META-INF/misc-spring.xml,\
META-INF/counter-spring.xml,\
META-INF/documentlibrary-spring.xml,\
META-INF/lock-spring.xml,\
META-INF/mail-spring.xml,\
META-INF/mail-spring-jms.xml,\
META-INF/portal-spring.xml,\
META-INF/portal-spring-jcr.xml,\
META-INF/portal-spring-jms.xml,\
META-INF/ext-spring.xml
Now at the end add one more line, you guess know which one: META-INF/ext-data-source-spring.xml so our final EXT_ENV/ext-impl/src/portal-ext.properties looks like:
##
## You can override portal.properties by specifying your own settings in this
## file.
##
spring.configs=\
META-INF/activemq-spring-jms.xml,\
META-INF/data-source-spring.xml,\
META-INF/misc-spring.xml,\
META-INF/counter-spring.xml,\
META-INF/documentlibrary-spring.xml,\
META-INF/lock-spring.xml,\
META-INF/mail-spring.xml,\
META-INF/mail-spring-jms.xml,\
META-INF/portal-spring.xml,\
META-INF/portal-spring-jcr.xml,\
META-INF/portal-spring-jms.xml,\
META-INF/ext-spring.xml,\
META-INF/ext-data-source-spring.xml
It’s over with configuration. Lets build and see what happens
4,Let's build
Lets do from dos box in EXT_ENV/ext-impl folder: Ant build-service
No errors should appear. After generation is done, let’s do quick and dirty tirck to save some time. By now we should have two classes:
EXT_ENV\ext-impl\src\com\blah\blah\blah\blah\service\impl\TrainingLocalServiceImpl.java
EXT_ENV\ext-service\src\com\blah\blah\blah\blah\service\persistence\TrainingUtil.java
Open both if your favorite editor (be carefull don’t change TrainingUtil.java by accident!):
In your TrainingLocalServiceImpl class add import to TrainingUtil, e.g. import com.blah.blah.blah.service.persistence.TrainingUtil;
copy public functions from TraningUtil, starting from the first one (including that one) to the countAll() (including that one as well).
paste them inside the TrainingLocalServiceImpl class
Delete all static keywords (Find/replace static to space)
Find/Replace or rename all getPersistence() to TrainingUtil
That’s all. However this is really a bad way to get TrainingLocalServiceImpl class implemented ! You need to add business logic to TrainingLocalServiceImpl. For the sake of simplicity of this article I have above trick to make it shorter.
Now rerun ant to promote our new public interface to other classes:
Ant build-service Ant compile Ant jar Ant deploy
This is end of java programing, if we might call it that way...
Note that after build-service that you did here again, few new classes were generated. One of them will be important for use later, and that's not located in persistance package (like TrainingUtil was that we mentioned above)!
Create database and table
Last task is to create table in the training database, and create database as well. Use your favorite tool to create database. DDL to create table is in EXT_ENV/sql/portal-tables.sql, open it and search for Training. If it's not there, just type "ant" from dos box in EXT_ENV/sql and it will get generated.
create table Training (
userId LONG not null primary key,
dogName VARCHAR(75) null,
wifeName VARCHAR(75) null
);
If using MySql you might want to modify it like this:
CREATE TABLE `training` (
`userId` bigint(20) NOT NULL DEFAULT '0',
`dogName` varchar(75) DEFAULT NULL,
`wifeName` varchar(75) DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
You can add two lines to table manually:
insert into training.training values (1,"tom","anna");
insert into training.training values (2,"boxy","silvy");
相信在此过程中会出现一个问题..用ant 执行service.xml 的时候回出来找不到资源文件的。不用管它;直接在ext-impl/build-parent.xml文件中加入下列内容:
<target name="build-service-portlet-training">
<antcall target="build-service">
<param name="service.file" value="src/com/ext/portlet/training/service.xml" />
</antcall>
</target>
<注意位置> <target name="build-service-portlet-reports">
直接用ant 在ext-impl 中执行
build-service-portlet-training
这样配置就完成了..具体的做数据展现的过程请参考...user2的例子做!