Liferay 7.1.2中JSF Bean @Reference注入OSGI服务为空问题求助
Let's break down exactly what's going wrong here and how to fix it.
The Core Issue: Conflicting Instance Managers
Your RegisterSearchBean is annotated with both @ManagedBean (managed by the JSF container) and @Component (managed by the OSGi container). This creates two separate instances of the bean:
- The JSF container creates an instance for your view, but this instance never goes through OSGi's dependency injection process—so the
@Referenceannotation is completely ignored, leaving_applicationServicesnull. - The OSGi container creates another instance that does get the service injected, but this isn't the instance your JSF page is actually using.
Fix 1: Switch to CDI Beans (Recommended for Liferay 7.x)
Liferay's OSGi integration works seamlessly with CDI, so replacing the JSF @ManagedBean with CDI's @Named lets OSGi handle both bean management and dependency injection properly. Here's the revised code:
@Named("registerSearchBean") @ViewScoped @Component( immediate = true, service = RegisterSearchBean.class ) public class RegisterSearchBean implements Serializable { public String message; @Reference private ApplicationServices _applicationServices; @PostConstruct public void initBean(){ getSearchFiltersForRegister(); } public void getSearchFiltersForRegister(){ message = _applicationServices.getSearchFiltersForRegister("asd"); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
Key Changes:
- Replaced
@ManagedBeanwith@Named(CDI's standard bean annotation) - Updated the
@Component'sserviceproperty to explicitly reference the bean class (avoids generic type issues) - Added
Serializable(required for@ViewScopedbeans)
Fix 2: Manually Fetch OSGi Service (If You Must Keep @ManagedBean)
If you need to stick with the JSF managed bean pattern, you can manually look up the OSGi service instead of relying on @Reference. Just be sure to clean up the service reference when the bean is destroyed:
@ManagedBean(name = "registerSearchBean") @ViewScoped public class RegisterSearchBean implements Serializable { public String message; private ApplicationServices _applicationServices; private ServiceReference<ApplicationServices> _serviceRef; @PostConstruct public void initBean(){ BundleContext bundleContext = FrameworkUtil.getBundle(RegisterSearchBean.class).getBundleContext(); _serviceRef = bundleContext.getServiceReference(ApplicationServices.class); if (_serviceRef != null) { _applicationServices = bundleContext.getService(_serviceRef); } getSearchFiltersForRegister(); } public void getSearchFiltersForRegister(){ if (_applicationServices != null) { message = _applicationServices.getSearchFiltersForRegister("asd"); } else { message = "Service unavailable"; } } @PreDestroy public void cleanup(){ BundleContext bundleContext = FrameworkUtil.getBundle(RegisterSearchBean.class).getBundleContext(); if (_serviceRef != null) { bundleContext.ungetService(_serviceRef); } } // Getters and setters remain the same }
Important Notes for This Approach:
- Add OSGi Core API dependency to your JSF module's
build.gradle:dependencies { compileOnly group: 'org.osgi', name: 'osgi.core', version: '6.0.0' } - This requires manual service lifecycle management, which is error-prone—stick with Fix 1 if possible.
Quick Validation Checks
Before testing your fix, verify these basics:
- Run
lbin Liferay's Gogo Shell to confirm your API and service provider modules are inActivestate. - Run
service:list ApplicationServicesto ensure your service is registered in the OSGi registry. - Double-check your JSF module's
build.gradleincludes a compile-only dependency on your API module.
内容的提问来源于stack exchange,提问作者Georgi D.

