Detecting Unresolved OSGi Components

Liferay Portal includes Gogo shell commands that come in handy when trying to diagnose a problem due to an unresolved OSGi component. The specific tools to use depend on the component framework of the unresolved component. Most Liferay Portal components are developed using Declarative Services (DS), also known as SCR (Service Component Runtime). An exception to this is Liferay Portal’s Service Builder services, which are provided as Dependency Manager (DM) components. Both Declarative Services and Dependency Manager are Apache Felix projects.

The troubleshooting instructions are divided into these sections:

Declarative Services Components

Start with DS, since most Liferay Portal components, apart from Service Builder components, are DS components. Suppose one of your bundle’s components has an unsatisfied service reference. How can you detect this? Two ways:

Declarative Services Unsatisfied Component Scanner

Here are the steps for enabling the unsatisfied component scanner:

  1. Create a file com.liferay.portal.osgi.debug.declarative.service.internal.configuration.UnsatisfiedComponentScannerConfiguration.cfg.

  2. Add the following file content:

    unsatisfiedComponentScanningInterval=5
    
  3. Copy the file into [LIFERAY_HOME]/osgi/configs.

The scanner detects and logs unsatisfied service component references. The log message includes the class that contains the reference, the bundle’s ID, and the referenced component type.

Here’s an example scanner message:

11:18:28,881 WARN  [Declarative Service Unsatisfied Component Scanner][UnsatisfiedComponentScanner:91]
Bundle {id: 631, name: com.liferay.blogs.web, version: 2.0.0}
    Declarative Service {id: 3333, name: com.liferay.blogs.web.internal.portlet.action.EditEntryMVCRenderCommand, unsatisfied references:
        {name: ItemSelectorHelper, target: null}
    }

The message above warns that service component com.liferay.blogs.web.internal.portlet.action.EditEntryMVCRenderCommand has an unsatisfied reference to a component of type ItemSelectorHelper. The referencing component’s ID (SCR ID) is 3333 and the component belongs to bundle 631.

ds:unsatisfied Command

Another way to detect unsatisfied component references is to invoke the Gogo shell command ds:unsatisfied.

  • ds:unsatisfied shows all unsatisfied services
  • ds:unsatisfied [BUNDLE_ID] shows the bundle’s unsatisfied services

To view more detailed information about the component with the unsatisfied reference, use the command scr:info [component ID]. For example, the following command does this for the component ID 1701:

g! scr:info 1701
*** Bundle: org.foo.bar.command (507)
Component Description:
    Name: org.foo.bar.command
    Implementation Class: org.foo.bar.command.FooBarCommand
    Default State: enabled
    Activation: delayed
    Configuration Policy: optional
    Activate Method: activate
    Deactivate Method: deactivate
    Modified Method: -
    Configuration Pid: [org.foo.bar.command]
    Services:
        org.foo.bar.command.DuckQuackCommand
    Service Scope: singleton
    Reference: Duck
        Interface Name: org.foo.bar.api.Foo
        Cardinality: 1..1
        Policy: static
        Policy option: reluctant
        Reference Scope: bundle
    Component Description Properties:
        osgi.command.function = foo
        osgi.command.scope = bar
    Component Configuration:
        ComponentId: 1701
        State: unsatisfied reference
        UnsatisfiedReference: Foo
        Target: null
        (no target services)
        Component Configuration Properties:
        component.id = 1701
        component.name = org.foo.bar.command
        osgi.command.function = foo
        osgi.command.scope = bar

In the Component Configuration section, UnsatisfiedReference lists the unsatisfied reference’s type. This bundle’s component isn’t working because it’s missing a Foo service. Now you can focus on why Foo is unavailable. The solution may be as simple as starting or deploying a bundle that provides the Foo service.

Service Builder Components

Liferay Portal’s Service Builder modules are implemented using Spring. Liferay Portal uses the Apache Felix Dependency Manager to manage Service Builder modules’ OSGi components via the Portal Spring Extender module.

When developing a Liferay Service Builder application, you might encounter a situation where your application has an unresolved Spring-related OSGi component. This could occur, for example, if you update your application’s database schema but forget to trigger an upgrade (for information on creating database upgrade processes for your Liferay Portal applications, see the tutorial Creating an Upgrade Process for Your App).

These features detect unresolved Service Builder related components.

Unavailable Component Scanner

The Liferay Foundation application suite’s Unavailable Component Scanner reports missing components in modules that use Service Builder. Here are the steps for enabling the scanner:

  1. Create configuration file com.liferay.portal.osgi.debug.spring.extender.internal.configuration.UnavailableComponentScannerConfiguration.cfg.

  2. In the configuration file, set the time interval (in seconds) between scans:

    unavailableComponentScanningInterval=5
    
  3. Copy the file into folder [LIFERAY_HOME]/osgi/configs.

The scanner reports Spring extender dependency manager component status on the set interval. If all components are registered, the scanner sends a confirmation message.

11:10:53,817 INFO  [Spring Extender Unavailable Component Scanner][UnavailableComponentScanner:166] All Spring extender dependency manager components are registered

If a component is unavailable, it reports an error like this one:

11:13:08,851 WARN  [Spring Extender Unavailable Component Scanner][UnavailableComponentScanner:173] Found unavailable component in bundle com.liferay.screens.service_1.0.28 [516].
Component ComponentImpl[null com.liferay.portal.sprin[email protected]1541eee] is unavailable due to missing required dependencies: ServiceDependency[interface com.liferay.blogs.service.BlogsEntryService null].

Component unavailability, such as what’s reported above, can occur when declarative services components and Service Builder components are published and used in the same module. We recommend you publish DS components and Service Builder components in separate modules.

ServiceProxyFactory

Liferay Portal’s logs report unresolved Service Builder components too. For example, Liferay Portal logs an error when a Service Proxy Factory can’t create a new instance of a Service Builder based entity because a service is unresolved.

The following code demonstrates using a ServiceProxyFactory class to create a new entity instance:

private static volatile MessageBus _messageBus =
    ServiceProxyFactory.newServiceTrackedInstance(
        MessageBus.class, MessageBusUtil.class, "_messageBus", true);

This message alerts you to the unavailable service:

11:07:35,139 ERROR [localhost-startStop-1][ServiceProxyFactory:265] Service "com.liferay.portal.kernel.messaging.sender.SingleDestinationMessageSenderFactory" is unavailable in 60000 milliseconds while setting field "_singleDestinationMessageSenderFactory" for class "com.liferay.portal.kernel.messaging.sender.SingleDestinationMessageSenderFactoryUtil", will retry...

Based on the message above, there’s no bundle providing the service com.liferay.portal.kernel.messaging.sender.SingleDestinationMessageSenderFactory.

To check your Service Builder modules for unresolved Spring components, you can use the Dependency Manager’s dm Gogo shell command, which is explained here:

For example, to get diagnostic information about Service Builder components, use the dependencymanager:dm command. This command lists all Service Builder components, their required services, and whether each required service is available.

Related Topics

Calling Non-OSGi Code that Uses OSGi Services

Felix Gogo Shell

OSGi Basics For Liferay Development

0 (0 Votes)
Why Aren’t JSP overrides I Made Using Fragments Showing? Previous