Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Liferay 7: OSGi Component as prototype
Hi, I'm trying to create multiple instances of a single OSGi-component, but have not succeeded yet. In Liferay 6, I would use spring-beans (having 'prototype'-property set) to get a separate instance for each e.g. user. In Liferay 7 I'm using OSGi and the common use case of the OSGi-components is to manage them as singletons. I've found that these Components can be Prototyped (scope= ServiceScope.PROTOTYPE), but I'm not sure that this approach is correct. Maybe I should use other way to accomplish mutliple instances (not OSGi)? Thanks!
How are you creating multiple instances? What is your usecase?
What are you trying to accomplish? One instance per bundle? One instance per component (per require)? Maybe even one instance per request?
What are you trying to accomplish? One instance per bundle? One instance per component (per require)? Maybe even one instance per request?
Hi Christoph, I need to create a separate Component instance for each loggedIn user in OSGi environment. So I plan to use (scope= ServiceScope.PROTOTYPE), but I'm not sure that this is the correct way. Looking forward to you reply.
For each logged in user or for each request? I am not sure, why you want one instance per user. If you want to keep data in it, I'd rather use a cache mechanism or some other storage.
In any case, PROTOTYPE_REQUIRED is not sufficient, you will still, by default get only one instance per component.
@Component A {
@Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
Something instance_for_A;
}
@Component B {
@Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
Something instance_for_B;
}
While the instances in A and B are different, there are still only two of them. You either need to use a factory or some different approach. With PROTOTYPE you could do something like this:
@Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
public void setFactory(ComponentServiceObjects<Something> factory) {
this.factory = factory;
}
Something x = factory.getService();
... do something with x
factory.ungetService(x);
But I am not sure, how this helps you for your usecase. Maybe it does, I don't know.
In any case, PROTOTYPE_REQUIRED is not sufficient, you will still, by default get only one instance per component.
@Component A {
@Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
Something instance_for_A;
}
@Component B {
@Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
Something instance_for_B;
}
While the instances in A and B are different, there are still only two of them. You either need to use a factory or some different approach. With PROTOTYPE you could do something like this:
@Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
public void setFactory(ComponentServiceObjects<Something> factory) {
this.factory = factory;
}
Something x = factory.getService();
... do something with x
factory.ungetService(x);
But I am not sure, how this helps you for your usecase. Maybe it does, I don't know.
Christoph, thanks a lot for your reply, I've imlemented the approach you've proposed and I do able to create an instance for each request. That's cool. But I also need to keep that instance within user session. I put it to PortletSession and I don't think it's right. My use case is - I have a 'calculation-tool' that should keep intermediate values and some math-operations performed by the user, I keep them now in an instance produced by the factory. This produced instance, in turn, is stored to user session (PortletSession), so the user could always return to prev calculation step. But when a portlet session expires this instance is not removed from the memory (until the bundle is restarted).
You've also mentioned to use a cache, can you give a hint on a class that can do it? I can also store this values to DB, but I don't want it since there are many not loggedIn users will use this calc-tool.
You've also mentioned to use a cache, can you give a hint on a class that can do it? I can also store this values to DB, but I don't want it since there are many not loggedIn users will use this calc-tool.
I think, you should not store a component anywhere. While I tried to explain what you can do to you, I don't think that the approach is sound.
I would create a simple DTO (data transfer object) to hold the data. Store the data you need in there. When you need to do calculations, give them to the components as parameter. We use DTOs quite a lot to transfer data through the various layers.
This doesn't solve your storage problem, though. The main question is: Can you afford to lose that object at any time? If it contains only intermediate values and basically is used to speedup things, a cache is the best option. If losing these data is really bad, you should persist them in the database.
For cache, you can use the SingleVM or the MultiVM cache. Here is some Liferay code that uses it. If you have no cluster, use SingleVM, if you have a cluster, then it depends. SingleVM could still be fine for your usecase. You probably need no listeners, you just need to put and fetch objects.
https://github.com/liferay/liferay-portal/blob/7.2.x/portal-impl/src/com/liferay/portal/template/BaseTemplateResourceCache.java
I would create a simple DTO (data transfer object) to hold the data. Store the data you need in there. When you need to do calculations, give them to the components as parameter. We use DTOs quite a lot to transfer data through the various layers.
This doesn't solve your storage problem, though. The main question is: Can you afford to lose that object at any time? If it contains only intermediate values and basically is used to speedup things, a cache is the best option. If losing these data is really bad, you should persist them in the database.
For cache, you can use the SingleVM or the MultiVM cache. Here is some Liferay code that uses it. If you have no cluster, use SingleVM, if you have a cluster, then it depends. SingleVM could still be fine for your usecase. You probably need no listeners, you just need to put and fetch objects.
https://github.com/liferay/liferay-portal/blob/7.2.x/portal-impl/src/com/liferay/portal/template/BaseTemplateResourceCache.java
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™