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 中使用它但没有成功。
附加信息:
- 该项目是一个 gradle LiferayWorkaspace。
- Api 和服务模块是通过 Liferay 插件生成的
模块文件夹。
- JSF 模块是通过 gradle 的 maven 原型生成的
在 "war" 文件夹中支持。
- 依赖项已正确定义,并且已全部正确部署在
Liferay 服务器。至少它看起来是这样....部署时没有出现丢失 classes 的错误。
我哪里做错了,为什么应用程序服务总是空的?
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
我目前正在使用 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 中使用它但没有成功。
附加信息:
- 该项目是一个 gradle LiferayWorkaspace。
- Api 和服务模块是通过 Liferay 插件生成的 模块文件夹。
- JSF 模块是通过 gradle 的 maven 原型生成的 在 "war" 文件夹中支持。
- 依赖项已正确定义,并且已全部正确部署在 Liferay 服务器。至少它看起来是这样....部署时没有出现丢失 classes 的错误。
我哪里做错了,为什么应用程序服务总是空的?
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