Prototype scope is super important. It's true we don't have a huge number
of uses (it may be less than 1% of all services), but where you need them
they are incredibly useful, particularly in modelling behaviours defined
outside the realm of OSGi.

For instance, JAX-RS expects resources to be instantiated per request
(where it can do it's own internal form of injection) so publishing a
resource as a service really should be done as prototype scope otherwise
you will surely mess up your state.

CDI expects (Portable) Extensions to be instantiated exactly one time (and
can have their own state since they are also injected as beans) and so,
since the OSGi CDI bundle can be restarted AND in order to support legacy
Extension implementations you have to pretty much assure that these are
provided as prototype scope services so that you never reuse the instances.

So these have many real uses where otherwise you'd be forced to use a
non-osgi factory model.

- Ray



On Wed, Mar 11, 2020 at 9:30 AM Peter Kriens via osgi-dev <
osgi-dev@mail.osgi.org> wrote:

> It all depends ... In general state can be managed in many different ways.
> Prototype scope is too much in your face, too much boilerplate, that is why
> I avoid it. It works nicely behind the scenes though like DS and CDI. I do
> not think I've ever used them so far. (Which is a self perpetuating truth,
> I know.)
>
> PK
>
>
>
> On 11 Mar 2020, at 13:26, Alain Picard <pic...@castortech.com> wrote:
>
> Peter and Tim,
>
> Thanks for the pointers. The error was caused by some invalid use of a
> disposed object. This was using factory components and I switched all of it
> to use prototype components instead which IMHO are easier to manage.
>
> And Peter to your question about using prototype scope, those objects
> contain state and it is my understanding that prototype scope is required
> in those cases.
>
> Thanks
> Alain
>
>
> On Mon, Mar 2, 2020 at 9:39 AM Peter Kriens <peter.kri...@aqute.biz>
> wrote:
>
>> Some remarks:
>>
>> * Yes, it is thread safe. In OSGi we mark all thread safe types with the
>> @ThreadSafe annotation.
>> * The error message is not in the log you listed. Since the log contains
>> a deactivation message, I hope you're handling the case corrected that
>> you're being called after deactivation? Seems too simple, but anyway ... :-)
>>
>> * And for something completely different, is there any reason you use the
>> prototype scope? You real code might need it but for this code it just
>> looks like making it accidentally complex?
>> * And last but not least, you seem to be using slf4j? Did you wire up the
>> OSGi log to it? I've seen cases where the information was in the OSGi log
>> but those messages were discarded.
>>
>> Kind regards,
>>
>> Peter Kriens
>>
>>
>> On 2 Mar 2020, at 12:03, Alain Picard via osgi-dev <
>> osgi-dev@mail.osgi.org> wrote:
>>
>> Question: The method getDiagnosticForEObject can be called by different
>> threads. Can this be the source of the issue? I see that
>> ComponentServiceObject is tagged as ThreadSafe, but?
>>
>> Alain
>>
>>
>> On Mon, Mar 2, 2020 at 5:47 AM Alain Picard <pic...@castortech.com>
>> wrote:
>>
>>> Tim,
>>>
>>> I don't think so. BaValidationManagerExt is used in only 1 place and it
>>> is instantiated in activate and released in deactivate:
>>> @Component(
>>> factory = ValidationManager.CONFIG_FACTORY,
>>> service = ValidationManager.class
>>> )
>>> public final class CoreValidationManager extends
>>> CDODefaultTransactionHandler1 implements ValidationManager,
>>> CDOTransactionHandler2 {
>>> ...
>>> @Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
>>> private ComponentServiceObjects<ValidationManagerExt> extenderFactory;
>>> private ValidationManagerExt extender;
>>>
>>> @Activate
>>> private void activate() {
>>> log.trace("Activating {}", getClass()); //$NON-NLS-1$
>>>
>>> extender = extenderFactory.getService();
>>> }
>>>
>>> @Deactivate
>>> private void deactivate() {
>>> log.trace("Deactivating {}", getClass()); //$NON-NLS-1$
>>> extenderFactory.ungetService(extender);
>>> }
>>>
>>> Cheers,
>>> Alain
>>>
>>> Alain Picard
>>> Chief Strategy Officer
>>> Castor Technologies Inc
>>> o:514-360-7208
>>> m:813-787-3424
>>>
>>> pic...@castortech.com
>>> www.castortech.com
>>>
>>>
>>> On Mon, Mar 2, 2020 at 3:40 AM Tim Ward <tim.w...@paremus.com> wrote:
>>>
>>>> Hi Alain,
>>>>
>>>> Is it possible that someone has a reference to a BaValidationManagerExt
>>>> service instance that they aren’t releasing after ungetting it (or that
>>>> they’re holding onto after it has been unregistered)? It might be an SCR
>>>> bug, but it’s more likely to be some code holding onto a component instance
>>>> that it shouldn’t.
>>>>
>>>> Best Regards,
>>>>
>>>> Tim
>>>>
>>>> On 29 Feb 2020, at 13:29, Alain Picard via osgi-dev <
>>>> osgi-dev@mail.osgi.org> wrote:
>>>>
>>>> Hi
>>>>
>>>> I am having a very intermittent issue with getService on a prototype
>>>> component. This is called hundreds of times and I put a breakpoint a few
>>>> weeks ago and have now gotten the error.
>>>>
>>>> I have this class:
>>>> @Component(scope=ServiceScope.PROTOTYPE,
>>>> property= org.osgi.framework.Constants.SERVICE_RANKING + ":Integer=10"
>>>> )
>>>> public final class BaValidationManagerExt implements
>>>> ValidationManagerExt {
>>>> private final Logger log = LoggerFactory.getLogger(getClass());
>>>>
>>>> @Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
>>>> private ComponentServiceObjects<Validator> validatorFactory;
>>>>
>>>> @Activate
>>>> private void activate() {
>>>> log.trace("Activating {}/{}", getClass(),
>>>> System.identityHashCode(this)); //$NON-NLS-1$
>>>> }
>>>>
>>>> @Deactivate
>>>> private void deactivate() {
>>>> log.trace("Deactivating {}/{}", getClass(),
>>>> System.identityHashCode(this)); //$NON-NLS-1$
>>>> }
>>>> ....
>>>> @Override
>>>> public Diagnostic getDiagnosticForEObject(EObject eObj) {
>>>> log.trace("Getting diagnostic for {}", eObj); //$NON-NLS-1$
>>>> Validator validator = validatorFactory.getService();
>>>>
>>>> if (validator != null) {
>>>> try {
>>>> return validator.runValidation(false, Collections.singletonMap(eObj,
>>>> new HashSet<>()),
>>>> new NullProgressMonitor()).getB();
>>>> }
>>>> finally {
>>>> validatorFactory.ungetService(validator);
>>>> }
>>>> }
>>>> else {
>>>> log.error("Validator Service not found for {}", eObj, new Throwable());
>>>> //$NON-NLS-1$
>>>> return Diagnostic.CANCEL_INSTANCE;
>>>> }
>>>> }
>>>> }
>>>>
>>>> and the validator:
>>>> @Component(
>>>> scope = ServiceScope.PROTOTYPE,
>>>> property= org.osgi.framework.Constants.SERVICE_RANKING + ":Integer=10"
>>>> )
>>>> public final class BaValidator implements Validator {
>>>> private final Logger log = LoggerFactory.getLogger(getClass());
>>>>
>>>> private Map<EObject, Set<EObject>> elementsToValidate;
>>>> private Set<EObject> validated = Sets.newHashSet();
>>>> private boolean batch;
>>>>
>>>> private EditingDomain domain;
>>>> private AdapterFactory adapterFactory;
>>>>
>>>> @Reference
>>>> private volatile List<ValidationProvider> validationProviders;
>>>>  //NOSONAR as per OSGi 112.3.9.1
>>>>
>>>> @Reference
>>>> private ValidationUtils validationUtils;
>>>>
>>>> @Activate
>>>> private void activate() {
>>>> log.trace("Activating {}/{}", getClass(),
>>>> System.identityHashCode(this)); //$NON-NLS-1$
>>>> }
>>>>
>>>> @Deactivate
>>>> private void deactivate() {
>>>> log.trace("Deactivating {}/{}", getClass(),
>>>> System.identityHashCode(this)); //$NON-NLS-1$
>>>> }
>>>> ...
>>>> }
>>>>
>>>> The error is on the highlighted line, which happens since getService
>>>> returns null.
>>>>
>>>> As can be seen here, ValidatorFactory serviceObjects is null which
>>>> seems to be what makes it return null:
>>>> ComponentServiceObjectsImpl [instances=[], serviceObjects=null,
>>>> deactivated=false, hashCode=301166435]
>>>>
>>>> I am not seeing any special in the logs (tracing is on). Just before I
>>>> see a number of successful call to the same code with the last one being:
>>>> just before in the logs:
>>>> 08:00:45.854 [Worker-1: Create Diagram] TRACE c.c.i.v.b.p.BaValidator -
>>>> Activating class
>>>> com.castortech.iris.validation.ba.provider.BaValidator/1297753057
>>>> 08:00:45.857 [Worker-1: Create Diagram] TRACE c.c.i.v.b.p.BaValidator -
>>>> Notify 4 listeners with diagnostics ([Diagnostic OK
>>>> source=com.castortech.iris.ba.validation code=0
>>>>  data=[RadialDiagramImpl{[cdoID->6558b1f9-dbcf-4e9d-b7b8-73779b5ada8f]
>>>> 08:00:45.858 [Worker-1: Create Diagram] TRACE c.c.i.v.b.p.BaValidator -
>>>> Deactivating class
>>>> com.castortech.iris.validation.ba.provider.BaValidator/1297753057
>>>>
>>>>
>>>> Has anyone seen this before or can provide some pointers to address
>>>> and/or debug this.
>>>>
>>>> Thanks
>>>> Alain
>>>>
>>>> _______________________________________________
>>>> OSGi Developer Mail List
>>>> osgi-dev@mail.osgi.org
>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>>
>>>>
>>>> _______________________________________________
>> OSGi Developer Mail List
>> osgi-dev@mail.osgi.org
>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>
>>
>>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev



-- 
*Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
 (@rotty3000)
Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
 (@Liferay)
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to