Skip to content

What is @Reference annotation

The @Reference annotation is a crucial part of Liferay’s OSGi (Declarative Services) ecosystem, enabling dependency injection between components. This guide covers all aspects of @Reference with practical examples.

  • Purpose: Declares a dependency on an OSGi service.
  • Effect: The OSGi container injects the required service automatically.
  • Location: From org.osgi.service.component.annotations.
classDiagram
    class YourComponent {
        -injectedService: SomeService
        +activate() void
        +modified() void
        +deactivate() void
    }

    class SomeService {
        <>
        +doWork() void
    }

    class SomeServiceImpl {
        +doWork() void
    }

    YourComponent --> SomeService : @Reference
    SomeService <|.. SomeServiceImpl : implements
@Reference
private SomeService _someService;
AttributeTypeDefaultDescription
cardinalityReferenceCardinalityMANDATORYDefines if the reference is required (MANDATORY) or optional (OPTIONAL)
policyReferencePolicySTATICDynamic vs static binding (STATIC or DYNAMIC)
policyOptionReferencePolicyOptionRELUCTANTHow to handle multiple services (GREEDY, RELUCTANT)
targetString""LDAP filter for service selection
unbindString"-unbind"Method to call when service is removed
serviceClass<?>InferredExplicit service interface type
nameString""Reference name for debugging
@Reference
private UserLocalService _userLocalService;
  • Fails if service is unavailable
  • Most common pattern in Liferay
@Reference(cardinality = ReferenceCardinality.OPTIONAL)
private volatile SomeOptionalService _optionalService;
  • Component works even if service is missing
  • Use volatile for dynamic cases
@Reference(
target = "(component.name=com.example.MySpecialImpl)"
)
private MyInterface _specialService;
@Reference(
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
private volatile SomeDynamicService _dynamicService;
  • Handles service coming/going at runtime
  • Common for connectors to external systems
@Reference(unbind = "_unsetService")
private SomeService _service;
protected void _unsetService(SomeService service) {
_service = null;
}
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC
)
private volatile List<EventHandler> _eventHandlers;
@Reference(
target = "(service.ranking=100)",
unbind = "_unsetHighPriorityService"
)
private HighPriorityService _highPriorityService;
  1. Prefer constructor injection (Liferay 7.4+) when possible:

    @Component(service = MyComponent.class)
    public class MyComponent {
    private final SomeService _someService;
    @Activate
    public MyComponent(@Reference SomeService someService) {
    _someService = someService;
    }
    }
  2. Use volatile for dynamic references

  3. Always provide unbind methods for complex dependencies

  4. Avoid field injection in @ReferenceCardinality.MULTIPLE cases

IssueSolution
Null referenceCheck cardinality (should be MANDATORY for required services)
Service not foundVerify target filter and service availability (lb in Gogo shell)
Memory leaksEnsure proper unbind methods for dynamic references
Circular dependenciesUse constructor injection or redesign component hierarchy
@Component(service = UserExport.class)
public class UserExport {
@Reference
private UserLocalService _userLocalService;
@Reference(
target = "(model.class.name=com.liferay.portal.kernel.model.User)",
unbind = "-"
)
private ModelResourcePermission<User> _userModelResourcePermission;
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC
)
private volatile AuditMessageProcessor _auditProcessor;
}
  • @Reference is Liferay’s primary dependency injection mechanism
  • Supports both static and dynamic service binding
  • Proper configuration prevents runtime issues
  • Combines well with @Component for modular architecture

Next Steps:

  1. Explore OSGi service trackers for advanced scenarios
  2. Learn about component lifecycle with @Activate/@Deactivate
  3. Study Liferay’s service builder pattern

🚀 Pro Tip: Use @Reference with @Component(service=...) to build clean, maintainable services!