« 返回到 Expando

Adding Custom Attributes to Communities

Introduction #

This is an example of adding an Expando attribute called "title" on a com.liferay.portal.model.Group (a community).

Creating the Attribute #

void createAttribute(long companyId)
	ExpandoBridgeImpl expandoBridge = new ExpandoBridgeImpl(com.liferay.portal.model.Group.class.getName());
	if (expandoBridge.hasAttribute("title")) {
		log.debug("attribute title already exists");
	}
	else {
		log.info("adding title attribute");
		expandoBridge.addAttribute("title");
	}
}


Setting Permissions for Community Members #

void setPermissions(long companyId) {
	ExpandoBridgeImpl expandoBridge = new ExpandoBridgeImpl(com.liferay.portal.model.Group.class.getName());
	Role guest = RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST);
	Role member = RoleLocalServiceUtil.getRole(companyId, RoleConstants.COMMUNITY_MEMBER);
	ExpandoColumn column = ExpandoColumnLocalServiceUtil.getColumn(
		expandoBridge.getClassName(),
		ExpandoTableConstants.DEFAULT_TABLE_NAME,
		"title");
	String[] actionsRO = new String[] { ActionKeys.VIEW };
	String[] actionsRW = new String[] { ActionKeys.VIEW, ActionKeys.UPDATE };
	// make sure the resource exists
	Resource resource = ResourceLocalServiceUtil.addResource(
		companyId,
		ExpandoColumn.class.getName(),
		ResourceConstants.SCOPE_INDIVIDUAL,
		String.valueOf(column.getColumnId()));

	PermissionLocalServiceUtil.setRolePermissions(guest.getRoleId(), actionsRO, resource.getResourceId());
	PermissionLocalServiceUtil.setRolePermissions(member.getRoleId(), actionsRW, resource.getResourceId());
}


Using the Attribute #

Java #

void updateTitle(Group group, String title) {
	group.getExpandoBridge().setAttribute("title", title);
	log.info("updated group " + group.getName() +
		      ", set title = " + twinspace.getExpandoBridge().getAttribute(""));
}

Velocity #

Use the community (=Group) title in the theme, for ex. in portal_normal.vm

#set ($community_title = $themeDisplay.getScopeGroup().getExpandoBridge().getAttribute("title"))


Troubleshooting #

Permissions Error #

  1. Instead of using the ExpandoBridge you can use ExpandoTableLocalServiceUtil and ExpandoColumnLocalServiceUtil. These services don't use permission checking. This is a bit more code.
  2. You can temporarily set a permissionChecker with PermissionThreadLocal.setPermissionChecker(pc). Don't forget to reset it to the original one after you are done.
0 附件
89948 查看
平均 (2 票)
满分为 5,平均得分为 5.0。
评论
讨论主题回复 作者 日期
When creating the custom attribute inside a... Peter Mesotten 2009年9月28日 上午1:59
Hi Peter, did you solve your this problem? I'm... Sven Ehlert 2009年10月9日 上午6:21
There are two solutions around this problem: 1.... Martin Goldhahn 2009年10月19日 上午7:47
He Peter, In Liferay 6.2 you can use the method... Rami MASMOUDI 2014年7月7日 上午5:24
Rami, Thanks for your reply. It worked. Anil T 2015年8月17日 上午1:42
How do i know / find out required role(s) for... Scott Langeberg 2010年5月5日 下午5:53
There are methods like addAttribute(String... Hiran Chaudhuri 2011年8月18日 下午2:53
I am in the same boat as Scott. How do you... Rob Chan 2011年8月31日 上午10:31
addAttribute int type definition is listed in... Jens Straube 2012年4月19日 上午3:42
Deprecated. Use the methods that receive... Christopher Jimenez 2013年7月17日 上午7:54

When creating the custom attribute inside a startup hook I get the following permission exception. I probably need to set the according permission to add an expando column for the user. But which user do I have to address here? And how should I set the permissions? I really want to avoid using ExpandoXXXLocalServiceUtil methods. Is this possible in startup hooks?

com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized
at com.liferay.portal.service.base.PrincipalBean.getPermissionChecker(PrincipalBean­.java:77)
at com.liferay.portlet.expando.service.impl.ExpandoColumnServiceImpl.addColumn(Expa­ndoColumnServiceImpl.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav­a:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils­.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(Ref­lectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(Transa­ctionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInv­ocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.j­ava:204)
at $Proxy95.addColumn(Unknown Source)
at com.liferay.portlet.expando.service.ExpandoColumnServiceUtil.addColumn(ExpandoCo­lumnServiceUtil.java:60)
at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.addAttribute(ExpandoBri­dgeImpl.java:98)
at be.aca.liferay.samples.expando.ExampleStartupHook.createAttribute(ExampleStartup­Hook.java:39)
at be.aca.liferay.samples.expando.ExampleStartupHook.doRun(ExampleStartupHook.java:­29)
at be.aca.liferay.samples.expando.ExampleStartupHook.run(ExampleStartupHook.java:21­)
at com.liferay.portal.kernel.events.InvokerSimpleAction.run(InvokerSimpleAction.jav­a:52)
at com.liferay.portal.deploy.hot.HookHotDeployListener.initEvent(HookHotDeployListe­ner.java:582)
at com.liferay.portal.deploy.hot.HookHotDeployListener.initEvents(HookHotDeployList­ener.java:643)
at com.liferay.portal.deploy.hot.HookHotDeployListener.doInvokeDeploy(HookHotDeploy­Listener.java:237)
at com.liferay.portal.deploy.hot.HookHotDeployListener.invokeDeploy(HookHotDeployLi­stener.java:98)
at com.liferay.portal.kernel.deploy.hot.HotDeployUtil._doFireDeployEvent(HotDeployU­til.java:108)
at com.liferay.portal.kernel.deploy.hot.HotDeployUtil._fireDeployEvent(HotDeployUti­l.java:153)
at com.liferay.portal.kernel.deploy.hot.HotDeployUtil.fireDeployEvent(HotDeployUtil­.java:43)
at com.liferay.portal.kernel.servlet.PortletContextListener.portalInit(PortletConte­xtListener.java:113)
at com.liferay.portal.kernel.util.PortalInitableUtil.init(PortalInitableUtil.java:4­8)
at com.liferay.portal.kernel.servlet.PortletContextListener.contextInitialized(Port­letContextListener.java:109)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843­)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1217)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:293)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.ja­va:117)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1337­)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChild­ren(ContainerBase.java:1601)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChild­ren(ContainerBase.java:1610)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(Containe­rBase.java:1590)
at java.lang.Thread.run(Thread.java:595)
在 09-9-28 上午1:59 发帖。
Hi Peter, did you solve your this problem? I'm having the exact same issue.
在 09-10-9 上午6:21 发帖以回复 Peter Mesotten
There are two solutions around this problem:
1. Instead of using the ExpandoBridge you can use ExpandoTableLocalServiceUtil and ExpandoColumnLocalServiceUtil. These services don't use permission checking. This is a bit more code.
2. You can temporarily set a permissionChecker with PermissionThreadLocal.setPermissionChecker(pc). Don't forget to reset it to the original one after you are done.
在 09-10-19 上午7:47 发帖以回复 Peter Mesotten
How do i know / find out required role(s) for user to have, when updating Group Expando (such as group.getExpandoBridge().setAttribute("title", title);)?

That is, in some situations, my user can setAttribute() on the group expando. However, I have other user(s) / environments / roles, whereby the user is getting the error below.

I've tried giving the user full owner / admin rights, but still getting error. If there is related documentation, i'd greatly appreciate a link!:

2010-05-05 16:57:49,432 INFO (http-172.19.20.203-8080-3) 16:57:49,417 ERROR [ExpandoBridgeImpl:280] com.liferay.portal.security.auth.PrincipalException
com.liferay.portal.security.a­uth.PrincipalException
at com.liferay.portlet.expando.service.permission.ExpandoColumnPermission.check(Exp­andoColumnPermission.java:67)
at com.liferay.portlet.expando.service.impl.ExpandoValueServiceImpl.addValue(Expand­oValueServiceImpl.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav­a:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils­.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(Ref­lectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:149)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(Meth­odInvocationProceedingJoinPoint.java:77)
at com.liferay.portal.spring.aop.ServiceHookAdvice.invoke(ServiceHookAdvice.java:90­)
at sun.reflect.GeneratedMethodAccessor318.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav­a:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGive­nArgs(AbstractAspectJAdvice.java:627)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(Abstrac­tAspectJAdvice.java:616)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.j­ava:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(Transa­ctionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInv­ocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveM­ethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.j­ava:204)
at $Proxy219.addValue(Unknown Source)
at com.liferay.portlet.expando.service.ExpandoValueServiceUtil.addValue(ExpandoValu­eServiceUtil.java:52)
at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.setAttribute(ExpandoBri­dgeImpl.java:275)
在 10-5-5 下午5:53 发帖。
There are methods like
addAttribute(String name)
addAttribute(String name, int type)
addAttribute(String name, int type, Serializable default)

How do you know what type to use for e.g. Date fields?
在 11-8-18 下午2:53 发帖。
I am in the same boat as Scott. How do you explicitly give users permissions to use ExpandoBridge?
在 11-8-31 上午10:31 发帖以回复 Hiran Chaudhuri
addAttribute int type definition is listed in com.liferay.portlet.expando.model.ExpandoColumnConstants
在 12-4-19 上午3:42 发帖以回复 Rob Chan
Deprecated.
Use the methods that receive 'companyId'
在 13-7-17 上午7:54 发帖以回复 Hiran Chaudhuri
He Peter,
In Liferay 6.2 you can use the method addAttribute(String name, boolean secure)
with secure=false to escape the permission exception emoticon
在 14-7-7 上午5:24 发帖以回复 Peter Mesotten
Rami, Thanks for your reply. It worked.
在 15-8-17 上午1:42 发帖以回复 Rami MASMOUDI