You need to enable JavaScript to run this app. Liferay 7.0 Gradle项目:JSF Portlet使用Kaleo API时服务注入为null问题
优惠活动
大模型
产品
解决方案
定价
更多

Liferay 7.0 Gradle项目:JSF Portlet使用Kaleo API时服务注入为null问题

Liferay 7.0 Gradle项目JSF Portlet中接入Kaleo工作流API的实现方案

问题根因

  • 原MVC Portlet的实现类带有@Component注解,属于OSGi框架托管的声明式服务组件,OSGi的服务绑定机制可正常识别类上的@Reference注解,自动注入匹配的Kaleo服务实例,因此可正常运行。
  • 移植到JSF Portlet场景时,直接将带@Reference注解的代码写入JSF/CDI容器托管的类(如@ManagedBean标注的托管Bean)中,这类类完全由JSF容器管理生命周期,不纳入OSGi声明式组件的扫描范围,@Reference注解无对应处理器触发注入逻辑,最终得到的服务实例始终为null。

分步实现步骤

1. 修正build.gradle中的依赖配置

不要使用硬编码版本的compile打包方式,Kaleo相关API包由Liferay Portal运行时提供,只需配置编译期依赖即可,避免类加载冲突:

dependencies {
    // 替换原硬编码版本的compile配置
    compileOnly group: "com.liferay.portal", name: "com.liferay.portal.workflow.kaleo.api", version: "2.0.0"
    compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.0.0"
}

2. 实现OSGi托管的服务桥接层

编写独立的纯OSGi组件类,不添加任何JSF/CDI相关注解,完全由OSGi框架托管,在类内部通过@Reference完成Kaleo服务的正常注入:

@Component(
    immediate = true,
    service = KaleoServiceBridge.class
)
public class KaleoServiceBridge {
    // 该类属于OSGi托管组件,@Reference可正常生效
    @Reference
    private KaleoTaskInstanceTokenLocalService kaleoTaskInstanceTokenLocalService;

    // 对外封装Kaleo服务的调用逻辑
    public List<KaleoTaskInstanceToken> getAllTaskInstanceTokens() {
        if (kaleoTaskInstanceTokenLocalService == null) {
            return Collections.emptyList();
        }
        return kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceTokens(
            QueryUtil.ALL_POS,
            QueryUtil.ALL_POS
        );
    }
}

3. 将桥接类暴露给JSF容器

Liferay的JSF扩展原生支持将OSGi组件注册为JSF托管Bean,只需在桥接类上增加@JSFComponent注解,即可自动完成注册,无需额外桥接代码:

@Component(
    immediate = true,
    service = KaleoServiceBridge.class
)
// 新增该注解,将OSGi组件注册为JSF应用作用域托管Bean
@JSFComponent(
    name = "kaleoServiceBridge",
    scope = "application"
)
public class KaleoServiceBridge {
    // 原有逻辑保持不变
}

4. 在JSF场景中调用桥接服务

在JSF托管Bean或页面中直接使用已注册的桥接Bean即可,无需在JSF托管类上添加@Reference注解。例如在JSF托管Bean中调用:

@ManagedBean
@RequestScoped
public class WorkflowMBean {
    public List<KaleoTaskInstanceToken> getTaskTokenList() {
        // 通过JSF上下文获取已由OSGi完成服务注入的桥接实例
        KaleoServiceBridge bridge = (KaleoServiceBridge) FacesContext.getCurrentInstance()
            .getExternalContext()
            .getApplicationMap()
            .get("kaleoServiceBridge");
        return bridge.getAllTaskInstanceTokens();
    }
}

常见注意事项

  • 禁止在JSF/CDI容器托管的类(带@ManagedBean、@Named、@RequestScoped等注解的类)上使用@Reference注解,这类类不受OSGi组件容器管理,注解完全无效。
  • 不要将Kaleo的LocalService实例直接存入JSF请求/会话作用域,服务引用的生命周期与OSGi组件绑定,硬引用可能在服务版本更新后出现失效问题,所有调用统一通过桥接层完成。
  • 依赖配置不要将Kaleo API包打进自有bundle,使用compileOnly配置即可,避免和Portal运行时提供的类产生版本冲突。

内容的提问来源于stack exchange,提问作者Chirag Lakhamani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.03 10:06:03