Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-71624

Service Builder fails with many-to-many relationship where Primary Key is of type String

    Details

      Description

      Description
      If you try to run the build-service task a module or plugin whose service.xml consists of a many:many mapping table between two or more entities, and one of those entities has a Primary Key column of type String, the service builder will fail. The mapping table java inside of ModelImpl.java fails to be built correctly, because getSqlType("String") returns null, since it doesn't have enough information to determine if it should return a VARCHAR or a CLOB.

      Steps to reproduce
      1. Download the attached blade-servicebuilder.zip file and unzip it into a modules SDK.
      2. Run the gradlew buildService task inside of the blade.servicebuilder.svc directory.

      Expected Result: The gradlew buildService task completes successfully.
      Actual Result: The gradlew buildService task throws an error:

      11:22:18,989 ERROR [runtime:60] Error executing FreeMarker template
      FreeMarker template error:
      The following has evaluated to null or missing:
      ==> serviceBuilder.getSqlType(mapColumn.getType())  [in template "com/liferay/portal/tools/service/builder/dependencies/model_impl.ftl" at line 306, column 68]
      
      ----
      Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
      ----
      
      ----
      FTL stack trace ("~" means nesting-related):
              - Failed at: #assign sqlType = serviceBuilder.getS...  [in template "com/liferay/portal/tools/service/builder/dependencies/model_impl.ftl" at line 306, column 49]
      ----
      
      Java stack trace (for programmers):
      ----
      freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
              at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:131)
              at freemarker.core.Assignment.accept(Assignment.java:136)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:268)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlock(IteratorBlock.java:220)
              at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:194)
              at freemarker.core.Environment.visitIteratorBlock(Environment.java:572)
              at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:78)
              at freemarker.core.IteratorBlock.accept(IteratorBlock.java:64)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.Environment.visitAndTransform(Environment.java:425)
              at freemarker.core.CompressedBlock.accept(CompressedBlock.java:37)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:268)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlock(IteratorBlock.java:220)
              at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:194)
              at freemarker.core.Environment.visitIteratorBlock(Environment.java:572)
              at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:78)
              at freemarker.core.IteratorBlock.accept(IteratorBlock.java:64)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.Environment.process(Environment.java:302)
              at freemarker.template.Template.process(Template.java:325)
              at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:47)
              at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:37)
              at com.liferay.portal.tools.service.builder.ServiceBuilder._processTemplate(ServiceBuilder.java:5463)
              at com.liferay.portal.tools.service.builder.ServiceBuilder._createModelImpl(ServiceBuilder.java:2716)
              at com.liferay.portal.tools.service.builder.ServiceBuilder.<init>(ServiceBuilder.java:757)
              at com.liferay.portal.tools.service.builder.ServiceBuilder.main(ServiceBuilder.java:219)
      Please set these arguments. Sample values are:
      
              service.api.dir=${basedir}/../portal-kernel/src
              service.auto.import.default.references=true
              service.auto.namespace.tables=false
              service.bean.locator.util=com.liferay.portal.kernel.bean.PortalBeanLocatorUtil
              service.build.number=1
              service.build.number.increment=true
              service.hbm.file=${basedir}/src/META-INF/portal-hbm.xml
              service.impl.dir=${basedir}/src
              service.input.file=${service.file}
              service.model.hints.configs=classpath*:META-INF/portal-model-hints.xml,META-INF/portal-model-hints.xml,classpath*:META-INF/ext-model-hints.xml,classpath*:META-INF/portlet-model-hints.xml
              service.model.hints.file=${basedir}/src/META-INF/portal-model-hints.xml
              service.osgi.module=false
              service.plugin.name=
              service.props.util=com.liferay.portal.util.PropsUtil
              service.read.only.prefixes=fetch,get,has,is,load,reindex,search
              service.resource.actions.configs=META-INF/resource-actions/default.xml,resource-actions/default.xml
              service.resources.dir=${basedir}/src
              service.spring.file=${basedir}/src/META-INF/portal-spring.xml
              service.spring.namespaces=beans
              service.sql.dir=${basedir}/../sql
              service.sql.file=portal-tables.sql
              service.sql.indexes.file=indexes.sql
              service.sql.sequences.file=sequences.sql
              service.target.entity.name=${service.target.entity.name}
              service.test.dir=${basedir}/test/integration
      
      You can also customize the generated code by overriding the default templates with these optional system properties:
      
              -Dservice.tpl.bad_alias_names=com/liferay/portal/tools/service/builder/dependencies/bad_alias_names.txt
              -Dservice.tpl.bad_column_names=com/liferay/portal/tools/service/builder/dependencies/bad_column_names.txt
              -Dservice.tpl.bad_json_types=com/liferay/portal/tools/service/builder/dependencies/bad_json_types.txt
              -Dservice.tpl.bad_table_names=com/liferay/portal/tools/service/builder/dependencies/bad_table_names.txt
              -Dservice.tpl.base_mode_impl=com/liferay/portal/tools/service/builder/dependencies/base_mode_impl.ftl
              -Dservice.tpl.blob_model=com/liferay/portal/tools/service/builder/dependencies/blob_model.ftl
              -Dservice.tpl.copyright.txt=copyright.txt
              -Dservice.tpl.ejb_pk=com/liferay/portal/tools/service/builder/dependencies/ejb_pk.ftl
              -Dservice.tpl.exception=com/liferay/portal/tools/service/builder/dependencies/exception.ftl
              -Dservice.tpl.extended_model=com/liferay/portal/tools/service/builder/dependencies/extended_model.ftl
              -Dservice.tpl.extended_model_base_impl=com/liferay/portal/tools/service/builder/dependencies/extended_model_base_impl.ftl
              -Dservice.tpl.extended_model_impl=com/liferay/portal/tools/service/builder/dependencies/extended_model_impl.ftl
              -Dservice.tpl.finder=com/liferay/portal/tools/service/builder/dependencies/finder.ftl
              -Dservice.tpl.finder_base_impl=com/liferay/portal/tools/service/builder/dependencies/finder_base_impl.ftl
              -Dservice.tpl.finder_util=com/liferay/portal/tools/service/builder/dependencies/finder_util.ftl
              -Dservice.tpl.hbm_xml=com/liferay/portal/tools/service/builder/dependencies/hbm_xml.ftl
              -Dservice.tpl.json_js=com/liferay/portal/tools/service/builder/dependencies/json_js.ftl
              -Dservice.tpl.json_js_method=com/liferay/portal/tools/service/builder/dependencies/json_js_method.ftl
              -Dservice.tpl.model=com/liferay/portal/tools/service/builder/dependencies/model.ftl
              -Dservice.tpl.model_cache=com/liferay/portal/tools/service/builder/dependencies/model_cache.ftl
              -Dservice.tpl.model_hints_xml=com/liferay/portal/tools/service/builder/dependencies/model_hints_xml.ftl
              -Dservice.tpl.model_impl=com/liferay/portal/tools/service/builder/dependencies/model_impl.ftl
              -Dservice.tpl.model_soap=com/liferay/portal/tools/service/builder/dependencies/model_soap.ftl
              -Dservice.tpl.model_wrapper=com/liferay/portal/tools/service/builder/dependencies/model_wrapper.ftl
              -Dservice.tpl.persistence=com/liferay/portal/tools/service/builder/dependencies/persistence.ftl
              -Dservice.tpl.persistence_impl=com/liferay/portal/tools/service/builder/dependencies/persistence_impl.ftl
              -Dservice.tpl.persistence_util=com/liferay/portal/tools/service/builder/dependencies/persistence_util.ftl
              -Dservice.tpl.props=com/liferay/portal/tools/service/builder/dependencies/props.ftl
              -Dservice.tpl.service=com/liferay/portal/tools/service/builder/dependencies/service.ftl
              -Dservice.tpl.service_base_impl=com/liferay/portal/tools/service/builder/dependencies/service_base_impl.ftl
              -Dservice.tpl.service_clp=com/liferay/portal/tools/service/builder/dependencies/service_clp.ftl
              -Dservice.tpl.service_clp_invoker=com/liferay/portal/tools/service/builder/dependencies/service_clp_invoker.ftl
              -Dservice.tpl.service_clp_message_listener=com/liferay/portal/tools/service/builder/dependencies/service_clp_message_listener.ftl
              -Dservice.tpl.service_clp_serializer=com/liferay/portal/tools/service/builder/dependencies/service_clp_serializer.ftl
              -Dservice.tpl.service_http=com/liferay/portal/tools/service/builder/dependencies/service_http.ftl
              -Dservice.tpl.service_impl=com/liferay/portal/tools/service/builder/dependencies/service_impl.ftl
              -Dservice.tpl.service_props_util=com/liferay/portal/tools/service/builder/dependencies/service_props_util.ftl
              -Dservice.tpl.service_soap=com/liferay/portal/tools/service/builder/dependencies/service_soap.ftl
              -Dservice.tpl.service_util=com/liferay/portal/tools/service/builder/dependencies/service_util.ftl
              -Dservice.tpl.service_wrapper=com/liferay/portal/tools/service/builder/dependencies/service_wrapper.ftl
              -Dservice.tpl.spring_xml=com/liferay/portal/tools/service/builder/dependencies/spring_xml.ftl
              -Dservice.tpl.spring_xml_session=com/liferay/portal/tools/service/builder/dependencies/spring_xml_session.ftl
      Exception in thread "main" FreeMarker template error:
      The following has evaluated to null or missing:
      ==> serviceBuilder.getSqlType(mapColumn.getType())  [in template "com/liferay/portal/tools/service/builder/dependencies/model_impl.ftl" at line 306, column 68]
      
      ----
      Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
      ----
      
      ----
      FTL stack trace ("~" means nesting-related):
              - Failed at: #assign sqlType = serviceBuilder.getS...  [in template "com/liferay/portal/tools/service/builder/dependencies/model_impl.ftl" at line 306, column 49]
      ----
      
      Java stack trace (for programmers):
      ----
      freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
              at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:131)
              at freemarker.core.Assignment.accept(Assignment.java:136)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:268)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlock(IteratorBlock.java:220)
              at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:194)
              at freemarker.core.Environment.visitIteratorBlock(Environment.java:572)
              at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:78)
              at freemarker.core.IteratorBlock.accept(IteratorBlock.java:64)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.Environment.visitAndTransform(Environment.java:425)
              at freemarker.core.CompressedBlock.accept(CompressedBlock.java:37)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48)
              at freemarker.core.Environment.visitByHiddingParent(Environment.java:345)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:268)
              at freemarker.core.IteratorBlock$IterationContext.executeNestedBlock(IteratorBlock.java:220)
              at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:194)
              at freemarker.core.Environment.visitIteratorBlock(Environment.java:572)
              at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:78)
              at freemarker.core.IteratorBlock.accept(IteratorBlock.java:64)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.MixedContent.accept(MixedContent.java:54)
              at freemarker.core.Environment.visit(Environment.java:324)
              at freemarker.core.Environment.process(Environment.java:302)
              at freemarker.template.Template.process(Template.java:325)
              at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:47)
              at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:37)
              at com.liferay.portal.tools.service.builder.ServiceBuilder._processTemplate(ServiceBuilder.java:5463)
              at com.liferay.portal.tools.service.builder.ServiceBuilder._createModelImpl(ServiceBuilder.java:2716)
              at com.liferay.portal.tools.service.builder.ServiceBuilder.<init>(ServiceBuilder.java:757)
              at com.liferay.portal.tools.service.builder.ServiceBuilder.main(ServiceBuilder.java:219)
      :blade.servicebuilder.svc:buildService FAILED
      
      FAILURE: Build failed with an exception.
      
      * What went wrong:
      Execution failed for task ':blade.servicebuilder.svc:buildService'.
      > Process 'command 'C:\Program Files\Java\jdk1.8.0_71\bin\java.exe'' finished with non-zero exit value 1
      
      * Try:
      Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
      
      BUILD FAILED
      

      You can also try modifying the service.xml file so that fooId is of type "long". In this case, the gradlew buildService task will succeed, proving that the service.xml is valid and that this bug only affects primary columns of type String.

      Reproduced in master (033be3425fd9f1d3be0b9446dea7c602dae9532c)
      Reproduced in ee-7.0.x (ba4aac94ed2ee70447d22830ef4829d09539e2f6)
      Reproduced in ee-6.2.x (7144732cd67e0e5680cf5c108f864a8bac098eab)

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  3 years, 14 weeks, 4 days ago

                  Packages

                  Version Package
                  6.2.X EE
                  7.0.0 DXP FP14
                  7.0.0 DXP SP3
                  7.0.3 CE GA4
                  7.0.X EE
                  7.1.X
                  Master