Hybris CronJob执行Groovy脚本遇方法重载歧义错误求助
解决Hybris CronJob中Groovy脚本的Transaction.execute方法重载歧义错误
问题描述
有一个用于根据多条件修改商品属性的Groovy脚本CronJob,去年第四季度运行正常,现在执行时触发方法重载歧义错误,错误信息如下:
Script execution has failed [reason: java.util.concurrent.ExecutionException: groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method de.hybris.platform.tx.DefaultTransaction#execute. Cannot resolve which method to invoke for [class UpdateWorker$_call_closure1] due to overlapping prototypes between: [interface de.hybris.platform.tx.TransactionBody] [interface de.hybris.platform.tx.TransactionBody$GenericTransactionBody]]
错误原因
de.hybris.platform.tx.DefaultTransaction类的execute方法存在两个重载版本,分别接收TransactionBody和TransactionBody$GenericTransactionBody接口参数。Groovy的闭包可以动态适配这两个接口的方法签名,导致JVM无法确定要调用哪个重载方法,从而触发歧义错误。这种情况通常是Hybris版本升级后新增了重载方法,或者Groovy类型推断逻辑变化导致的。
解决方案
方案1:显式指定闭包实现的接口
在调用execute方法时,将Groovy闭包强制转换为其中一个明确的接口(推荐TransactionBody),让JVM确定调用的方法。
修改UpdateWorker类中的call()方法里的Transaction.execute调用部分:
// 原代码 Transaction.current().execute( { lines.each { line -> // 原有逻辑... } } ) // 修改后代码 Transaction.current().execute({ lines.each { line -> // 原有逻辑保持不变... } } as de.hybris.platform.tx.TransactionBody)
方案2:使用显式匿名内部类代替闭包
通过创建TransactionBody接口的匿名内部类实例,明确指定实现的接口,彻底避免重载歧义:
// 修改后的Transaction.execute调用 Transaction.current().execute(new de.hybris.platform.tx.TransactionBody() { @Override void execute() throws Exception { lines.each { line -> sessionService.executeInLocalViewWithParams(params, new SessionExecutionBody(){ public void executeWithoutResult(){ // 原有内部逻辑完全保留... } }) } } })
完整修改后的UpdateWorker.call()方法示例
def String call() { def startThread = new Date() privateLogger.info('IsNested transaction: ' + Transaction.current().isNested()) // 使用方案1的修改方式 Transaction.current().execute({ lines.each { line -> sessionService.executeInLocalViewWithParams(params, new SessionExecutionBody(){ public void executeWithoutResult(){ def queryForSubstitution = /select distinct {s.pk} from {Substitution as s} where ({s.partForSubstitutionCode} = ?productPk or {s.skuReplacementCode} = ?productPk) and {s.partForSubstitutionCode} is not null and {s.skuReplacementCode} is not null/ def productPk = line.getCode(); def queryParams = [:]; queryParams.put('productPk', productPk); final FlexibleSearchQuery fsQuery = new FlexibleSearchQuery(queryForSubstitution, queryParams); def substitutions = flexibleSearchService.search(fsQuery).getResult(); if(substitutions.size() == 0) { line.setSubstitutionCode(subCodeNoEntry); line.setSubstitutionIndicator(subIndicatorEmpty); } else{ def subFromList = []; def subToList = []; //Split into 2 list for(SubstitutionModel substitution : substitutions) { //These fields are mandatories during hotfolder process //Anyway are not mandatories in hybris sistem, this null check avoid to abort cronjob if(substitution.getPartForSubstitutionCode() != null && substitution.getSkuReplacementCode() != null) { if(substitution.getPartForSubstitutionCode() == productPk) { subFromList.add(substitution) } else { subToList.add(substitution) } } } //Calculate substitution code def substitutionCode; if(subFromList.size() == 0){ substitutionCode = subCodeNoEntry } else if(subFromList.size() == 1){ if(subFromList.get(0).getConditionalNotes() != null && !subFromList.get(0).getConditionalNotes().isEmpty()) { substitutionCode = subCodeMoreEntriesWithConditionalNotes } else{ substitutionCode = subCodeOneEntry } } else{ substitutionCode = subCodeMoreEntriesNoConditionalNotes for(SubstitutionModel substitution : substitutions) { if(substitution.getConditionalNotes() != null && !substitution.getConditionalNotes().isEmpty()){ substitutionCode = subCodeMoreEntriesWithConditionalNotes break } } } line.setSubstitutionCode(substitutionCode) //Calculate substitution indicator def substitutionIndicator; if(subFromList.size() > 0 && subToList.size() > 0){ substitutionIndicator = subIndicatorBoth } else if (subFromList.size() > 0 && subToList.size() == 0){ substitutionIndicator = subIndicatorForward } else if (subFromList.size() == 0 && subToList.size() > 0){ substitutionIndicator = subIndicatorPrevious } line.setSubstitutionIndicator(substitutionIndicator) } line.setTriggerSubstitutionCronjob(false) modelService.save(line) }}) } } as de.hybris.platform.tx.TransactionBody) def stopThread = new Date() def TimeDuration td = TimeCategory.minus( stopThread, startThread ) privateLogger.info('Sanitized ' + lines.size() + ' elements in' + td) return 'Sanitized ' + lines.size() + ' elements in' + td }
内容的提问来源于stack exchange,提问作者iamrooovic
相关产品推荐
相关产品推荐

