On Wed, Mar 11, 2020 at 10:02 AM Raymond Auge <raymond.a...@liferay.com> wrote:
> 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 > read "CDI container within a CDI bundle can be restarted" > 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) > -- *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