Liferay 门户:OSGI 模块化与 JSF 和 EJB- CDI 而不是 injecting/retrieveing 与 @Resource

Liferay Portal: OSGI Modularity with JSF and EJB- CDI not injecting/retrieveing with @Resource

我目前正在使用 tomcat 开发 Liferay 7.1.2.ga3 CE,并且正在阅读官方文档中教程的 OSGI 部分。 这个:Docs

我决定尝试使用最简单的项目。 我在我的 IntelliJ 想法中创建了一个 Liferay 工作区,并添加了一些组件,如教程中所述。

问题是它要么不注入,要么注入但不检索依赖关系,因为在这种情况下,在消费者中,_applicationServices 变量始终为 null。

编辑: 我在 Liferay 官方论坛上问过同样的问题: Question in Liferay.org

这是代码:

api:

@ProviderType
public interface ApplicationServices {
    String getSearchFiltersForRegister(String registerCode);
}

提供商:

@Component(
    immediate = true,
    property = {
    },
    service = ApplicationServices.class
)
public class ApplicationServicesImpl implements ApplicationServices {
    @Override
    public String getSearchFiltersForRegister(String registerCode) {
        return "OSGI modularity made service";
    }
}

消费者:

@ManagedBean(name = "registerSearchBean")
@ViewScoped
@Component(
        immediate = true,
        property = {
                "osgi.command.scope=getSearchFiltersForRegister",
                "osgi.command.function=getSearchFiltersForRegister"
        },
        service = Object.class
)
public class RegisterSearchBean {

        public String message;

        @Reference
        private ApplicationServices _applicationServices;

        @PostConstruct
        public void initBean(){
                getSearchFiltersForRegister();
        }

        public void getSearchFiltersForRegister(){
                ApplicationServices applicationServices=_applicationServices;
                message=applicationServices.getSearchFiltersForRegister("asd");
        }

        public String getMessage() {
                return message;
        }

        public void setMessage(String message) {
                this.message = message;
        }
}

注意: 我也曾尝试将 consumre 模块分离到不同的 class 并在此 bean 中使用它但没有成功。

附加信息:

我哪里做错了,为什么应用程序服务总是空的?

Neil Griffin在 liferay 论坛上广泛回答。:

Hi Georgi,Thanks so much for reaching out. You asked a very important question that deserves a thorough answer. Since JSF is a technology based on Java EE, it expects the project to be a Web Application ARchive (WAR) rather than a Java ARchive (JAR). When the WAR is deployed to $LIFERAY_HOME/deploy, Liferay will automatically convert the Java EE WAR to an OSGi Web Application Bundle (WAemoticon. Although WABs are first-class OSGi citizens, they do not participate in the build-time discovery of services via classes annotated with @Component. The more natural fit for WABs is CDI, which accomplishes deploy-time discovery of services by scanning the classpath.So the difficulty with the code that you pasted is this: You are combining OSGi Declarative Services build-time discovery (via @Component) with a CDI deploy-time discovery (via @ViewScoped). These need to be used in a mutually exclusive way -- In other words, they cannot be combined.Here's the encouraging news -- Liferay 7.1, 7.2, and 7.3 ship with weld-osgi-bundle.jar in $LIFERAY_HOME/modules and fully supports the CDI requirements of Portlet 3.0 via OSGi CDI Integration. This means it is possible to develop WARs that use JSR 330 @Inject in order to inject services from the OSGi Service Registry into CDI beans. It also makes it possible to publish CDI beans into the OSGi service registry. I recently gave a talk at Liferay DEVCON 2019 titled Portlet 3.0 MVCBean and PortletMVC4Spring that demonstrates the promise of OSGi CDI integration. If you have time, I recommend that you watch the presentation because it should help you get a better idea as to how it all works. But I'm sorry to say the JSF isn't quite able to take advantage of this yet. We're still working on our implementation of JSR 378, which makes it possible to deploy a JSF portlet within Liferay as a Portlet 3.0 "bean portlet" -- that's the part that enables all the OSGi CDI Integration functionality. We have it working in the 5.x branch of the liferay-faces-bridge-impl.git repository but won't be able to cut a production release until JSR 378 is complete.So unless you want to experiment with the 5.x version of the bridge, then I recommend that you follow the advice in the my DEVCON 2016 presentation titled Developing WABs With a View to the Future in which I describe how to use a ServiceTracker in order to acquire services from the OSGi Service Registry within a WAR portlet like those required by JSF.Having said that, it would probably be a good idea for you to develop OSGi services with @Component (Declarative Services) in a JAR module. The JAR module can be deployed separately from your JSF portlet WAR module. That way, you should be able to acquire the service (defined by @Component) from the OSGi Service Registry via the ServiceTracker in your JSR managed bean. Eventually, once we release JSR 378, you will be able to use JSR 330 @Inject instead of the ServiceTracker in order to inject your OSGi service into your JSF managed bean (managed by CDI via @javax.faces.view.ViewScoped). Just to clarify, again, in the future, you would want to use the CDI compatible version of the @ViewScoped annotation and not the one intended for use with the JSF Managed Bean Facility (MBF) which is @javax.faces.bean.ViewScoped.Kind Regards,Neil