RE: OSGi component defined inside ext-module not registered in SCR.

txapeldot ., modified 8 Months ago. Junior Member Posts: 91 Join Date: 1/15/15 Recent Posts

On the Documents & Media widget, I’m working on a task consisting of skipping the permission checking for special folders (defined by the user) and actions (ADD_FOLDER, ADD_SHORTCUT and ADD_DOCUMENT). In the method ‘com.liferay.document.library.web.internal.portlet.toolbar.contributor.DefaultDLPortletToolbarContributor.containsPermission()’, given a folderId, if the associated folder is one of the special folders defined by the user is derived by invoking a method located at an OSGi component defined in an external module.

The way I’m tackling this task consists of creating an ext-module (to override the base ‘com.liferay.document.library.web’ module), and, from within it, creating an OSGi component to invoke the service-providing method (located at the service-providing OSGI component). But the result has been unsuccessful as the invoking OSGi component doesn’t get activated. As a consequence, I wonder why an OSGi component defined inside an ext-module doesn’t get activated (same example on a current liferay module works as expected).

I’ve prepared a MCV example to summarize the behavior I target. The module ‘my-service-provider’ provides the target method; the ext-module ‘com.liferay.document.library.web.ext’ provides the calling method, and they are defined as it follows:

Liferay module: my-service-provider
-----------------------------------------------------------------------------------------------------

package my.service.provider;

@Component(immediate = true, property = {}, service = MyServiceProvider.class)
public class MyServiceProvider {

	public String getGreeting() {
		return "Hello World";
	}
}

 

Ext-module: com.liferay.document.library.web.ext
-----------------------------------------------------------------------------------------------------

package my.service.consumer;

@Component(immediate = true, property = {})
public class MyServiceConsumer {
	
	@Reference
	private MyServiceProvider myServiceProvider;
		
	@Activate
	public void activate() {
		
		logger.info("this.myServiceProvider.getClass(): " + this.myServiceProvider.getClass());
		logger.info("_completed");
	}

 

Once I check the 'activate()' method is not called, I query the SCR by typing the following commands from a GoGo shell:

g! lb -s | grep my-service-provider
   78|Active     |   10|my-service-provider (1.0.0)|1.0.0


g! scr:list 78
my.service.provider.MyServiceProvider in bundle 78 (my-service-provider:1.0.0) enabled, 1 instance.
    Id: 4305, State:ACTIVE
	
	
g! inspect cap service 78
my-service-provider_1.0.0 [78] provides:

my.service.provider.MyServiceProvider in bundle 78 (my-service-provider:1.0.0) enabled, 1 instance.
    Id: 4303, State:ACTIVE
service; my.service.provider.MyServiceProvider with properties:
   _portalInitialized.target = (module.service.lifecycle=portal.initialized)
   service.id = 4707
   service.bundleid = 78
   service.scope = bundle
   component.name = my.service.provider.MyServiceProvider
   component.id = 4303
   Used by:
      my.service.provider.MyServiceProvider_1.0.0 [78]
      my.service.nonext.consumer_1.0.0 [1066]

 

Then, I type the following commands as for the ext-module:

g! lb -s | grep com.liferay.document.library.web
  189|Resolved   |   10|com.liferay.document.library.web (3.0.146)|3.0.146
 1067|Active     |   10|com.liferay.document.library.web (3.0.146.ext)|3.0.146.ext
true


g! scr:list 1067 | grep MyServiceConsumer
false

So, I don't see the invoking OSGi component is registered in SCR, and that explains why the 'activated()' method is not called, but I don't know why that OSGi component is not registered.

Any clarification about why the invoking OSGI component is not being registered would be appreciated. Thanks.

 

thumbnail
David H Nebinger, modified 8 Months ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts

Bypassing security is never a good premise to start from. It opens a door for other bypasses that perhaps you may not like.

Given the requirements (certain users should have all perms in folders designated by an admin), I would still solve this using the permission system properly:

  1. Create a group.
  2. Put the designated members in the group.
  3. Create a role, give it all of the necessary permissions on files, folders, etc.
  4. Assign the role to the group.
  5. Assign the group to the folder.

All of this can be done programmatically (if that too is a requirement), but it is still secure (enforcing permissions to access folders and files), it uses published Liferay APIs, doesn't require an EXT module, etc.

I'm already guessing that you're not going to heed this advice and want to stay on the path you're on. The problem is two modules with the same symbolic name. That conflict (even though they have different versions) is going to cause all kinds of headaches.

In 7.4 you're either going to replace Liferay's bundle in the osgi/portal folder with your own or you're going to blocklist the Liferay module and use a unique symbolic name for your custom module.

Either way, these are pretty heavy-handed solutions because it means every update to Liferay you're going to be redoing all of this activity over and over again. The permissions approach that I outlined doesn't have any of these problems, which is why I would recommend it over an EXT module.

Generally, for anyone reading this post, understand that EXT modules will be the bain of your existence. There's a reason that Liferay deprecated and removed them completely in the quarterlies. They are not good solutions and while they can solve unique problems, they do so in the worst possible way.