文档编号 |
Liferay-01 |
版本 |
V 1.0 |
产品名称 |
Liferay |
Liferay技术文档
Huihoo.com
Huihoo – Enterprise Open
Source
许可协议:GNU FDL
http://www.gnu.org/licenses/fdl.html
2004年12月
修订记录
Date |
Modified
by |
Version |
Modification |
10/10/2004 |
Allen Long |
1.0 |
文档初始化 |
22/10/2004 |
Allen Long |
1.0 |
补充Liferay定制部分 |
|
|
|
|
|
|
|
|
|
|
|
|
感谢zh补充的Session EJBs and Hibernate 处理时序图 :)
Liferay技术文档
这是对Liferay的分析文档,且包含对Liferay的修改策略和方法。
本文档主要介绍基于 JSR-168规范(Portlet规范)的WEB应用软件设计;
本文档主要针对服务器端应用开发人员而编写.
开发的软件名称::Liferay的修改和重构;
1. Liferay http://www.liferay.com/
2. JSR-168 http://www.jcp.org/en/jsr/detail?id=168
。用户能通过以下接口访问portal
SOAP,RMI,Custom tunneling class
。HTML
and WML: Struts Servlet
。Web
Services : Axis Servlet
。J2ME,J2SE,J2EE:
Tunnel Servlet
使用了Stateless Session EJBs : local,remote访问
Session EJBs and Hibernate
l
使用EJB是为了使用其分布式的能力,如分布式cluster,cache和transaction(
Session EJB可以使应用在Web Server,EJB Server和Database Server三个层次上达到clustering的目的,便于系统今后的可扩展)
l
Liferay使用CMP技术达到持久性目的,此能力是通过hibernate来提供
l
每个portlet的持久性数据都拥有自己的ejb.xml,通过ant build-ejb命令的使用,其build tool使用的是XDoclet
l
使用JAAS提供其安全访问机制
l
处理流程
Struts Action -> Stateless Session EJB Facade ->
Persistence Helper Class -> Hibernate
我们以addesssbook部分的删除abcontact为列子来说明整个流程,见下图:
web页面输入constact的id来请求DeleteAction删除数据,DeleteAction调用代理类ABContractmanagerUtil来执行delete的功能。ABContractmanagerUtil封装了ejb的功能,而SessionBean本身也没进行delete的功能,而是通过封状了实现了Hibernate 的ABContactPersitence的ABContactUtil来代理的。ABContactPersitence同时维护数据库和缓存的数据,使之达到同步。
ABContactUtil还实现了listener和读取ABContactPersitence缓存的功能。
l
所有HTTP和WAP请求都通过MainServlet进行处理,MainServlet继承Struts的ActionServelt
l
所有页面的布局信息都集中在portal-web/docroot/WEB-INF/html/tiles下的文件中
一个很好的演示站点: http://www.funambol.com/
大部分EJBs,HBMs和Models都是通过ant build-ejb读取ejb.xml文件生成的
l
主要涉及两个表:abcontact, ,ablist
l
定义的model
com.liferay.portlet.addressbook.model.ABContact.java
com.liferay.portlet.addressbook.model.ABContactModel.java
com.liferay.portlet.addressbook.model.ABlist.java
com.liferay.portlet.addressbook.model.ABListModel.java
l
使用hibernate建立的对model的map
com.liferay.portlet.addressbook.ejb.ABContactHBM.java
com.liferay.portlet.addressbook.ejb.ABListHBM.java
l
持久性方法create,update,add,remove的定义
com.liferay.portlet.addressbook.ejb.ABContactPersistence.java
com.liferay.portlet.addressbook.ejb.ABListPersistence.java
l
定义的util
com.liferay.portlet.addressbook.ejb.ABContactUtil.java
com.liferay.portlet.addressbook.ejb.ABlistUtil.java
l
Pooling将使对象创建代价最小化
com.liferay.portlet.addressbook.ejb.ABContactPool.java
com.liferay.portlet.addressbook.ejb.ABListPool.java
l
Manager EJB 扩展
PrincipalSessionBean包含业务逻辑 Remote
com.liferay.portlet.addressbook.ejb.ABContactManagerEJB.java
com.liferay.portlet.addressbook.ejb.ABListManagerEJB.java
Helper classes are generated that reflect the Manager classes.
com.liferay.portlet.addressbook.ejb.ABContactManager.java
com.liferay.portlet.addressbook.ejb.ABContactManagerHome.java
com.liferay.portlet.addressbook.ejb.ABContactManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABContactManagerUtil.java
com.liferay.portlet.addressbook.ejb.ABListManager.java
com.liferay.portlet.addressbook.ejb.ABListManagerHome.java
com.liferay.portlet.addressbook.ejb.ABListManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABListManagerUtil.java
l
通过80端口访问管理类
com.liferay.portlet.addressbook.ejb.ABContactManagerHttp.java
com.liferay.portlet.addressbook.ejb.ABListManagerHttp.java
l
Local Manager classes that extend BasicSessionBean Loca
com.liferay.portlet.addressbook.ejb.ABContactLocalManagerEJB.java
com.liferay.portlet.addressbook.ejb.ABListLocalMangerEJB.java
l
Helper classes are generated.
com.liferay.portlet.addressbook.ejb.ABContactLocalManager.java
com.liferay.portlet.addressbook.ejb.ABContactLocalManagerHome.java
com.liferay.portlet.addressbook.ejb.ABContactLocalManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABContactLocalManagerUtil.java
com.liferay.portlet.addressbook.ejb.ABListLocalManager.java
com.liferay.portlet.addressbook.ejb.ABListLocalManagerHome.java
com.liferay.portlet.addressbook.ejb.ABListLocalManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABListLocalManagerUtil.java
l
远程访问类
com.liferay.portlet.addressbook.ejb.ABContactRemoteManager.java
com.liferay.portlet.addressbook.ejb.ABContactRemoteManagerEJB.java
com.liferay.portlet.addressbook.ejb.ABContactRemoteManagerHome.java
com.liferay.portlet.addressbook.ejb.ABContactRemoteManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABContactLocalManagerUtil.java
com.liferay.portlet.addressbook.ejb.ABListRemoteManager.java
com.liferay.portlet.addressbook.ejb.ABListRemoteManagerEJB.java
com.liferay.portlet.addressbook.ejb.ABListRemoteManagerHome.java
com.liferay.portlet.addressbook.ejb.ABListRemoteManagerHomeUtil.java
com.liferay.portlet.addressbook.ejb.ABListRemoteManagerUtil.java
////////////////
l
涉及两个表:bookmarksentry,bookmarksfolder
l
定义的model
com.liferay.portlet.bookmarks.model.BookmarksEntry
com.liferay.portlet.bookmarks.model.BookmarksEntryModel
com.liferay.portlet.bookmarks.model.BookmarksFolder
com.liferay.portlet.bookmarks.model.BookmarksFolderModel
l
使用hibernate建立的对model的map
com.liferay.portlet.bookmarks.ejb.BookmarksEntryHBM
com.liferay.portlet.bookmarks.ejb.BookmarksFolderHBM
l
Add,update,delete,find,remove,count等方法
com.liferay.portlet.bookmarks.ejb.BookmarksEntryPersistence
com.liferay.portlet.bookmarks.ejb.BookmarksFolderPersistence
…
portal.properties
位于:server/default/deploy/ext.ear/portal-ejb.jar目录下
一些条目
l
log.configure.log4j=true
l
users.id.validator=com.liferay.portal.UserIdValidatorc
l
# All locales must use UTF-8 encoding.
l
locales=zh_CN,zh_TW,nl_NL,en_US,fr_FR,de_DE,el_GR,it_IT,ja_JP,ko_KP,pt_BR,es_ES,tr_TR
l
struts.char.encoding=UTF-8
l
session.timeout=30
l
servlet.session.create.events=com.liferay.portal.events.SessionCreateAction
l
servlet.session.destroy.events=com.liferay.portal.events.SessionDestroyAction
l
principal.finder=com.liferay.portal.auth.BasicPrincipalFinder
// JAAS
l
auth.simultaneous.logins=true //允许不同会话同时login
l
login.events.post=com.liferay.portal.events.LoginPostAction
// login event
l
logout.events.post=com.liferay.portal.events.LogoutPostAction
// logout event
l
value.object.cacheable=true
l
cache.clear.on.startup=true // server start clear cache
l
tunnel.servlet.hosts=127.0.0.1
…
开发一个简单的hello world portlet,
package com.liferay.portlet.mytest;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import
javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.liferay.portal.util.Constants;
public class MyTestHelloWorld extends
GenericPortlet {
public
void doView(RenderRequest req, RenderResponse res)
throws
IOException, PortletException {
res.setContentType(Constants.TEXT_HTML);
res.getWriter().print("Hello
World!");
res.getWriter().print("This
is my test!");
}
public
void processAction(ActionRequest req, ActionResponse res)
throws
IOException, PortletException {
}
}
一.
对于定义一个portlet业务
1. 当配置一个Session Bean时,也就是说配置一个hibernate---ejb-----web时,在其portlet下必须配置一个与其业务相关的几个表的ejb.xml ,其中包含表的名,字段,主键,查询方法。
2. 只要是开发了一个Session Bean,则在ejb-jar.xml文件中定义,可以说,其包括了所有的Bean的描述。包括远程接口/本地接口,主接口,实现类,Bean类型等说明。
3. 而根据bean的开发,则必须是每个bean都是通过jndi来寻找远程/本地接口(jboss.xml)
而在liferay中,则是在jrun-ejb-jar.xml中进行为每一个Session Bean,一个jndi。
4. 而hibernate-mapping,跟数据库所发生的交互中,都在portlet-hbm.xml中定义。
5. 在EJB上开发Hibernate的事务处理一定不要写语句,因为已经在配置文件中JTA 即可。
实列:地址本的实现
1. 首先利用ABContactManagerHomeUtil获得主接口ABContactManagerHome,而主接口本身可以解决很多查找和创建的工作,在这儿实现的相当于是通过jndi和工厂类来实现的。(实现了对Hibernate的jndi绑定)
2. 但是如果要操作Bean的数据对象时,譬如对数据库要访问时,这时必须创建远程/本地接口对象ABContactManager.
3. 而ABcontactManagerEJB是对本地接口的实现类,即可进行数据操作,增加,删除,更新。
这是一个基本实现,而在这个基础上再作了处理,譬如加上了缓存的处理,还有一些中间代理。
在liferay上部署portlet
将mytest的目录copy到/server/default/deploy/ext.ear/portal-ejb.jar/com/liferay/portlet目录下
修改server/default/deploy/ext.ear/portal-web-complete.war/WEB-INF/portlet.xml ,
增加以下内容
<portlet>
<portlet-name>70</portlet-name>
<display-name>My
Hello World</display-name>
<portlet-class>com.liferay.portlet.mytest.MyTestHelloWorld</portlet-class>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<portlet-info>
<title>My
Hello World</title>
<short-title>My
Hello World</short-title>
<keywords>My
Hello World</keywords>
</portlet-info>
<security-role-ref>
<role-name>Power
User</role-name>
</security-role-ref>
<security-role-ref>
<role-name>User</role-name>
</security-role-ref>
</portlet>
修改server/default/deploy/ext.ear/portal-web-complete.war/WEB-INF/liferay-portlet.xml ,增加以下内容
<portlet id="70" struts-path="my_hello_world"
narrow="true" />
在liferay-display.xml中增加以下内容
<category name="category.test">
<portlet id="50" />
<portlet
id="47" />
<portlet
id="48" />
<portlet
id="EXT_1" />
<!--
begin of user defined -->
<portlet
id="70" />
<!--
end of user defined -->
</category>
然后通过定制页面portlet/test分类中选中My Hello World,然后返回到首页就可以看到那个portlet啦。
DevManage Exception:
You do not have the roles required
to access this portlet.
The
show-portlet-access-denied value, if set to true, means users are shown
that they do not have access to the portlet if they do not have access to the
portlet. The default value is set in portal.properties.
http://www.liferay.com/documentation/development/portlet.jsp
update layout.show.portlet.access.denied=true in line 523
layout.show.portlet.access.denied=false
新建一个device_manage
portlet 的过程
device
manage portlet
1.<portlet>
<portlet-name>100</portlet-name>
<display-name>DevManage</display-name>
<portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
<name>view-action</name>
<value>/device_manage/view</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle>
<security-role-ref>
<role-name>Power
User</role-name>
</security-role-ref>
<security-role-ref>
<role-name>User</role-name>
</security-role-ref>
</portlet>
2.D:\YHYliferay-ep-2.2.0rc4-jboss-tomcat\server\default\deploy\ext.ear\portal-ejb.jar\content\Language.propertity
add javax.portlet.title.100=DevManage
3.liferay-portlet.xml
add <portlet id="100"
struts-path="dev_manage" />
4.liferay-display.xml
<portlet
id="100" />
5.tiles-defs.xml
<!--yhy device_manage-->
<definition name="portlet.device_manage.view"
extends="portlet_default">
<put
name="portlet_content"
value="/portlet/device_manage/view_1.jsp" />
</definition>
6.stucts_config.xml
<!--yhy
device_manage-->
<action
path="/device_manage/add"
type="com.liferay.portlet.device_manage.action.AddAction">
<forward
name="portlet.device_manage.add"
path="portlet.device_manage.add.jsp" />
</action>
<action
path="/device_manage/update" type="com.liferay.portlet.device_manage.action.UpdateAction">
<forward
name="portlet.device_manage.update"
path="portlet.device_manage.update.jsp" />
</action>
<action
path="/device_manage/delete"
type="com.liferay.portlet.device_manage.action.DeleteAction" />
<action
path="/device_manage/view"
forward="portlet.device_manage.view" />
<!--yhy-->
主要关注以下两个目录
/portal/portal-ejb // 门户应用的业务层
/portal/portal-web
// 门户应用的表现层
portal-ejb包括:
。liferay提供的所有portlet的实现
。portal
需要jikes 编译器
通过jikes编译一个JAVA源程序
jikes
HelloWorld.java –classpath .:/usr/local/j2sdk1.4.2_05/jre/lib/rt.jar
安装Orion 2.0.2
下载 config.zip http://www.liferay.com/documentation/config.zip
替换 Orion下的config
修改 config/data-source.xml
修改 server.xml
创建一个文件
portal/util-java/classes/portal-ext.properties
加入 portal.ctx = /portal.
unzip source
/portal ,运行 ant start
147 public keyDown(Event e,int key) {
Semantic Error : The overridden method keyDown
修改/portal/build.properties
Javac.compiler=modern
// default value jikes
Javac.debug=off
// default value on
内存出错
修改ant-home/bin/ant.bat或ant
:runAnt
"%_JAVACMD%"
%ANT_OPTS% -Xmx512m -classpath "%LOCALCLASSPATH%"
"-Dant.home=%ANT_HOME%" org.apache.tools.ant.Main %ANT_ARGS%
%ANT_CMD_LINE_ARGS%
goto end
修改app.server.properties
app.server=/usr/local/orion
然后ant deploy
C:\liferay-ep-2.2.0rc4-jboss-jetty\server\default\deploy
liferay.xml
<datasources>
<local-tx-datasource>
<jndi-name>jdbc/LiferayPool</jndi-name>
<connection-url>
jdbc:mysql://localhost/lportal
</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>sa</user-name>
<password></password>
<min-pool-size>5</min-pool-size>
</local-tx-datasource>
</datasources>
mysql-connector-java-3.0.14-production-bin.jar
包放到
C:\liferay-ep-2.2.0rc4-jboss-jetty\server\default\lib
使用Xdoclet和hibernate生成代码
http://www.liferay.com/documentation/development/customizing.jsp
主要是对源代码进行修改和编译
要安装好jikes等工具
rpm –ivh
jikes-1.22-1.i586.rpm 这个版本不行
使用 jikes-1.18.tar.bz2
tar jxvf jikes-1.18.tar.bz2
./configure
make
make install
加入 export PATH=/usr/local/bin/jikes:$PATH到/etc/profile
执行/usr/local/bin/jikes
对三个版本做实验
。liferay-ep-2.2.0rc4-src.zip
。liferay-ep-2.2.0-src.zip
。liferay-ep-2.2.1-src.zip (为主)
unzip source
生成/portal目录
修改/portal/release.properties (以2.2.1为主)
lep.eclipse.dir=
/usr/local/portal/eclipse_workspace
lep.ext.dir=C:/SourceForge/liferay/ext to /usr/local/portal/ext
lep.source.dir=C:/SourceForge/liferar.src
to /usr/local/portal
or windows平台
lep.eclipse.dir=C:/portal/eclipse_workspace
lep.ext.dir=C:/portal/ext
lep.source.dir=C:/portal/portal
通过以下命令create ext
。ant start
。ant build-ext
生成的目录结构
/ext
/ext/downloads
/ext/ext-ear
/ext/ext-ejb
/ext/ext-lib
/ext/ext-web
/ext/lib
/ext/portlets
/ext/servers
/ext/sql
/ext/web-sites
修改ext/app.server.properties文件
lep.ext.dir=/usr/local/portal/ext
。ant build-eclipse 创建 /portal/eclipse_workspace目录 (需要2.2.1版本)
下载liferay-ep-2.2.0rc4-jboss.jetty.zip to /ext/downloads
或liferay-ep-2.2.1-jboss.jetty.zip
cd /ext/servers
ant
install-jboss-jetty
修改/ext/app.server.properties
设置 app.server.type=jboss-jetty
部署
/ext/ant deploy
运行
/ext/servers/jboss-jetty/bin/run.sh
http://localhost 成功运行 J
客户定制的jar,war在ext/ext-ear/modules 它允许你容易的update liferay,因为所有的功能都在这个目录下,包含
。cache-ejb.jar
。counter-ejb.jar
。documentlibrary-ejb.jar
。lock-ejb.jar
。mail-ejb.jar
。portal-ejb.jar
。portal-web.war
。tunnel-web.war
META-INF/application.xml
<application>
<display-name>Liferay
Enterprise Portal</display-name>
<module>
<ejb>cache-ejb.jar</ejb>
</module>
<module>
<ejb>counter-ejb.jar</ejb>
</module>
<module>
<ejb>documentlibrary-ejb.jar</ejb>
</module>
<module>
<ejb>lock-ejb.jar</ejb>
</module>
<module>
<ejb>mail-ejb.jar</ejb>
</module>
<module>
<ejb>portal-ejb.jar</ejb>
</module>
<module>
<ejb>ext-ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>portal-web-complete.war</web-uri>
<context-root>/</context-root>
</web>
</module>
<module>
<web>
<web-uri>tunnel-web.war</web-uri>
<context-root>/tunnel</context-root>
</web>
</module>
<security-role>
<role-name>users</role-name>
</security-role>
</application>
/ext/ext-ejb
包含的重要文件有:
。portal-ext.properties
。content/Language-ext.properties
。system-ext.properties
在ext/servers/jboss-jetty/server/default/deploy/ext.ear/portal-ejb.jar下
有以下重要条目:
。file.encoding=UTF8
。user.country=US // 在这里调整,使默认为中文 CN
。user.language=en // zh
# hibernate
。hibernate.configs=META-INF/cache-hbm.xml,META-INF/counter-hbm.xml,META-INF/mail-hbm.xml,META-INF/portal-hbm.xml,META-INF/ext-hbm.xml
。hibernate.connection.datasource=jdbc/LiferayPool
。hibernate.connection.provider_class=com.liferay.util.dao.hibernate.DSConnectionProvider
。hibernate.statement_cache.size=0
。hibernate.jdbc.batch_size=0
。hibernate.jdbc.use_scrollable_resultset=true
。hibernate.cglib.use_reflection_optimizer=false
。
hibernate.cache.provider_class=net.sf.hibernate.cache.HashtableCacheProvider
。hibernate.show_sql=false
# Set the JavaScript encoding.
com.liferay.util.JS.encoding=ISO-8859-1
/ext/ext-web
若没有/ext/ext-web/tmp 通过unjar脚本
unzip /ext/ext-ear/modules/portal-web.war
into /ext/ext-web/tmp
从ext/ext-web/docroot copy everything to /etx/ext-web/tmp
然后从ext/ext-web/tmp copy 到部署的服务器上
liferay的语言设置在
liferay-ep-2.2.0rc4-jboss-jetty\server\default\deploy\ext.ear\portal-ejb.jar\content
每种支持的语言对应两个文件:如中文
。Language_zh_CN.properties
用UTF-8格式定义的Portlet Titles,Category Title …
。Language_zh_CN.properties.native
定义了在屏幕上要显示的汉字
portal
addressbook: mail usage
modify the
file: $JBOSS-JETTY/server/default/deploy/mail-service.xml
change your mail account when login to the portal, in "my account".
2.2.1 地址薄暂时不能使用。
bug of
liferay 2.2.1 src
modify the
source: portal\tools\ext_tmpl\ext-web\build-parent.xml
add after line
68:
<unjar
src="${project.dir}/lib/dom4j.jar" dest="${classpath.jsp}"
/>
ref the vss.
需要重新编译整个liferay
rm –rf ext
。/portal/ant clean
。/portal/ant start
。/portal/ant build-ext
。/ext/servers/ant install-jboss-jetty
。/ext/ant deploy (要修改app.server.properites)
。/ext/servers/jboss-jetty/bin/run.sh
http://localhost/c/ 类似c这样的path在哪里定义的:
E:\src\liferay-ep-2.2.0rc4-src\portal\portal-ejb\src\com\liferay\portal\struts\PortalRequestProcessor.java
private static
String _PATH_C = "/c";
我们可将其该为portal
以后的地址 http://portal.rimoon.com
private static
String _PATH_BLOGS_FIND_ENTRY = "/blogs/find_entry";
private static
String _PATH_CALENDAR_IFRAME_EVENTS_PUBLIC =
"/calendar/_iframe_events_public";
private static
String _PATH_COMMON = "/common";
private static
String _PATH_COMMON_ERROR = "/common/error";
private static
String _PATH_J_SECURITY_CHECK = "/j_security_check";
private static
String _PATH_JOURNAL_GET_TEMPLATE = "/journal/get_template";
private static
String _PATH_MAIL_UPDATE_RECEIPT = "/mail/update_receipt";
private static
String _PATH_MY_ACCOUNT_CREATE_ACCOUNT =
"/my_account/create_account";
private static
String _PATH_PORTAL = "/portal";
private static
String _PATH_PORTAL_ADD_PAGE = "/portal/add_page";
private static
String _PATH_PORTAL_CHANGE_PASSWORD =
"/portal/change_password";
private static
String _PATH_PORTAL_ERROR = Constants.PORTAL_ERROR;
private static
String _PATH_PORTAL_LAST_PATH = "/portal/last_path";
private static
String _PATH_PORTAL_LAYOUT = "/portal/layout";
private static
String _PATH_PORTAL_LOGOUT = "/portal/logout";
private static
String _PATH_PORTAL_TERMS_OF_USE = "/portal/terms_of_use";
private static
String _PATH_PORTAL_UPDATE_TERMS_OF_USE =
"/portal/update_terms_of_use";
private static
String _PATH_PORTAL_PUBLIC = "/portal_public";
private static
String _PATH_PORTAL_PUBLIC_ABOUT = "/portal_public/about";
private static
String _PATH_PORTAL_PUBLIC_DISCLAIMER =
"/portal_public/disclaimer";
private static
String _PATH_PORTAL_PUBLIC_J_LOGIN =
"/portal_public/j_login";
private static
String _PATH_PORTAL_PUBLIC_LAYOUT = "/portal_public/layout";
private static
String _PATH_PORTAL_PUBLIC_LOGIN = "/portal_public/login";
private static
String _PATH_PORTAL_PUBLIC_PROTECTED =
"/portal_public/protected";
private static
String _PATH_PORTAL_PUBLIC_TCK = "/portal_public/tck";
private static
String _PATH_SHOPPING_NOTIFY = "/shopping/notify";