<< Back to previous view

[QB-2399] Groovy script that uses string interpolation in Promotion condition causes error when trying to view build
Created: 08/Apr/15  Updated: 15/May/15

Status: Open
Project: QuickBuild
Component/s: None
Affects Version/s: 6.0.10
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Scott Hunter Assigned To: Robin Shen
Resolution: Unresolved Votes: 0
Remaining Estimate: Unknown Time Spent: Unknown
Original Estimate: Unknown


 Description   
To reproduce:

1. Create two build configurations called "A" and "B".
2. Create a new promotion in "A" that promotes into "B". Set condition to "If specified script evaluates to true", and use this script:

groovy:

def foo = "a"
def bar = "${foo}"

return true


Run "A". The Overview page for "A" reports the error message:

Failed to evaluate below expression:
mvel:foo

Clicking on the build for "A" reports the error message:

Message: Failed to evaluate below expression:
mvel:foo

Root cause:

[Error: could not access: foo; in class: null]
[Near : {... Unknown ....}]
^
[Line: 1, Column: 0]
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getBeanProperty(ReflectiveAccessorOptimizer.java:611)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:323)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:135)
at org.mvel2.optimizers.dynamic.DynamicOptimizer.optimizeAccessor(DynamicOptimizer.java:66)
at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:139)
at org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:42)
at org.mvel2.MVEL.executeExpression(MVEL.java:1057)
at com.pmease.quickbuild.plugin.basis.BasisPlugin$26.evaluate(BasisPlugin.java:280)
at com.pmease.quickbuild.DefaultScriptEngine.evaluate(DefaultScriptEngine.java:88)
at com.pmease.quickbuild.DefaultScriptEngine.interpolate(DefaultScriptEngine.java:105)
at com.pmease.quickbuild.setting.configuration.promotion.ScriptPromoteCondition.satisfied(ScriptPromoteCondition.java:38)
at com.pmease.quickbuild.web.page.build.BuildPage.addPromotionButtons(BuildPage.java:822)
at com.pmease.quickbuild.web.page.build.BuildPage.onInitialize(BuildPage.java:453)
at org.apache.wicket.Component.fireInitialize(Component.java:924)
at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:1002)
at org.apache.wicket.Page.internalPrepareForRender(Page.java:278)
at org.apache.wicket.Component.render(Component.java:2280)
at org.apache.wicket.Page.renderPage(Page.java:1035)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:105)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:182)
at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:147)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:719)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:63)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:210)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:253)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:162)
at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:137)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
at com.pmease.quickbuild.web.MainServlet.service(MainServlet.java:124)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.eclipse.equinox.http.helper.FilterServletAdaptor$FilterChainImpl.doFilter(FilterServletAdaptor.java:56)
at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:82)
at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:243)
at org.eclipse.equinox.http.helper.FilterServletAdaptor.service(FilterServletAdaptor.java:37)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336)
at com.pmease.quickbuild.Quickbuild$DisableTraceFilter.doFilter(Quickbuild.java:1048)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:453)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:365)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485)
at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:926)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:988)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)
at org.eclipse.jetty.server.bio.SocketConnector$ConnectorEndPoint.run(SocketConnector.java:264)
at org.eclipse.jetty.server.ssl.SslSocketConnector$SslConnectorEndPoint.run(SslSocketConnector.java:670)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:701)


Complete stack:

com.pmease.quickbuild.QuickbuildException: Failed to evaluate below expression:
mvel:foo
at com.pmease.quickbuild.util.ExceptionUtils.wrapException(ExceptionUtils.java:89)
at com.pmease.quickbuild.DefaultScriptEngine.evaluate(DefaultScriptEngine.java:94)
at com.pmease.quickbuild.DefaultScriptEngine.interpolate(DefaultScriptEngine.java:105)
at com.pmease.quickbuild.setting.configuration.promotion.ScriptPromoteCondition.satisfied(ScriptPromoteCondition.java:38)
at com.pmease.quickbuild.web.page.build.BuildPage.addPromotionButtons(BuildPage.java:822)
at com.pmease.quickbuild.web.page.build.BuildPage.onInitialize(BuildPage.java:453)
at org.apache.wicket.Component.fireInitialize(Component.java:924)
at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:1002)
at org.apache.wicket.Page.internalPrepareForRender(Page.java:278)
at org.apache.wicket.Component.render(Component.java:2280)
at org.apache.wicket.Page.renderPage(Page.java:1035)
at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:105)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:182)
at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:147)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:719)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:63)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:210)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:253)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:162)


It seems like the script is incorrectly being evaluated as an MVEL string before being used.

A workaround is to avoid use of string interpolation in the groovy script. For example, replacing "${foo}" with foo + "" fixes the issue.

 Comments   
Comment by Robin Shen [ 08/Apr/15 11:28 PM ]
For all ${...} occurrences, QB interpolates them before executing the script as groovy. Ideally QB should not interpolate in this case, however for backward compatibility reason (some users are already relying this heavily), we can not make the change...
Comment by Scott Hunter [ 15/May/15 07:19 PM ]
I found that the escape syntax $!{ is a better workaround than avoiding string interpolation. It still requires writing QuickBuild-specific Groovy that doesn't work from a normal Groovy console (for testing scripts).

One thought I had for avoiding backwards compatibility problems would be to introduce a new prefix that disables interpolation. So, perhaps "groovy:" preserves the current behavior and "raw:groovy:" disables interpolation. I don't know if the new behavior would be useful for the other script languages or not.
Generated at Mon May 06 18:52:27 UTC 2024 using JIRA 189.