开发者

Liferays Service Builder - many-to-many relations

I'm trying to create a many-to-many between my own entity and the liferay Group entity. My service.xml looks like this

<entity name="EntityA" local-service="true" remote-service="false">

    <column name="entityAId" type="long" primary="true" />

    <column name="title" type="String" />
    <column name="summary" type="String" />
    <column name="authorId" type="long" />

    <column name="attachments" type="Collection" entity="EntityAAttachment" mapping-key="entityAId" />
    <column name="groups" type="Collection" entity="com.liferay.portal.Group" mapping-table="EntityAs_Groups" />

</entity>

According to the DTD of the service.xml this should generate a many-to-many relation but I only get this

Method public java.util.List com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(java.lang.String) throws java.io.IOException threw an exception when invoked on com.liferay.portal.tools.servicebuilder.ServiceBuilder@21ff3fcf
The problematic instruction:
----------
==> list serviceBuilder.getMappingEntities(column.mappingTable) as mapColumn [on line 201, column 49 in com/liferay/portal/tools/servicebuilder/dependencies/model_impl.ftl]
----------
Java backtrace for programmers:
----------
freemarker.template.TemplateModelException: Method public java.util.List com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(java.lang.String) throws java.io.IOException threw an exception when invoked on com.liferay.portal.tools.servicebuilder.ServiceBuilder@21ff3fcf
    at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:130)
    at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
    at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
    at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.Environment.visit(Environment.java:299)
    at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.IfBlock.accept(IfBlock.java:82)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:179)
    at freemarker.core.Environment.visit(Environment.java:417)
    at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.Environment.process(Environment.java:190)
    at freemarker.template.Template.process(Template.java:237)
    at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:49)
    at com.lifer开发者_运维技巧ay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:39)
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder._processTemplate(ServiceBuilder.java:4447)
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder._createModelImpl(ServiceBuilder.java:2420)
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.<init>(ServiceBuilder.java:1023)
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.<init>(ServiceBuilder.java:404)
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.main(ServiceBuilder.java:176)
Caused by: java.lang.NullPointerException
    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(ServiceBuilder.java:1366)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:840)
    at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:106)
    ... 32 more

What I'm doing wrong here? I'm using the latest Liferay stable 6.0.5


This is an unresolved bug in Liferay: https://issues.liferay.com/browse/LPS-49769

Changing the lexicographical order of your entities might solve this problem but resolve in incorrect generated source code.

Potential workaround by Mike Lenox at https://www.liferay.com/community/forums/-/message_boards/message/41347203 :

Potential workaround: I have a large model with a bunch of many-to-many mappings that always worked fine. I eventually stumbled across this bug when adding a new mapping. I finally noticed that some of my relationships should have triggered the bug, but didn't (lexigraphic order was greater than). At first I couldn't figure out why the old ones worked, but the new ones failed. Turns out that if you have a backwards many-to-many in the target entity, the builder works fine.

For instance, add a fooList attribute to FooBar to correspond to the fooBarList in Foo, both using the same mapping-table..

I suppose that this would only work for 2 custom entities unless you modify LR.

Another workaround is to define the mapping yourself as an entity, as suggested by http://blog.d-vel.com/home/-/blogs/service-builder-e-relazioni-many-to-many (in Italian):

<entity name="Autore_Libro" local-service="true">
 <column name="autoreId" type="long" primary="true" />
 <column name="libroId" type="long" primary="true" />
</entity>


I am pretty sure you can not make one-to-many nor many-to-many relationship between your entities and portal entities. At least not directly using the Service Builder. Take into account that your portlet and the portal are separate contexts.

And as suggested in other answer, NO. NEVER mess with the portal-impl.jar. It is highly discouraged.

I would suggest to simulate this relationship implementing the required methods in EntityAServiceImpl and EntityALocalServiceImpl classes. I think this will be the cleanest way to go.

Have a look at this..

https://dev.liferay.com/develop/tutorials/-/knowledge_base/6-2/writing-local-service-classes

Hope that helps


Lferay group entity,service and implementations are in portal-impl.jar which is under ROOT/web-inf/lib, so if you are trying to use that entity their implementation and service are out of scope, then you have two choices, either you move portal-impl to the global classpath of your runtime (which a bad choice cause you'll have to move all the other libs too) or you move portal-impl to your portlet class path (which is a bad choice too).. The best solution is to use a hook so portal-impl will be reachable..then move the lib that service-builder generates to global class path of your server tomcat/lib/ext so it will be in the scope of your portlet.it works fine for me. Add a reference before enclosing your entity

<reference package-path="com.liferay.portal" entity="Group" />
  1. deploy the hook
  2. it will generate the necessary tables
  3. stop tomcat
  4. Move the lib to global classpath
  5. restart Tomcat


for more on Liferay Servie builder Check out this post .

http://liferaydemystified.blogspot.com/2011/04/mvc-portlet-development-service-builder.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜