Hi Alain,

a little bit late but maybe some side notes to EMF and OSGi. EMF is not thread-safe. May it be possible that you share one ResourceSet/Resource over many Prototype instances?

This is in general not a good idea. In case you use EMF with Equinox, you should give each prototype instance an own ResourceSet instance. Otherwise you will sooner or later run into ConcurrentModificationException when adding/removing Resources to/from a ResourceSet. In any case sharing a ResourceSet over Prototype instance will also lead to memory leaking over the time, if you do not remove/cleanup the Resources after using them.

Using EObjects in a detached state can be helpful, but is not useful for some use-cases e.g. Validation / Compare, because you have to attach the objects before doing something.

You can also take look at our GeckoEMF. We have ResourceSets as a service, also as PROTOTYPE scoped. So you can get an own ResourceSet instance injected. We also have a ResourceSetFactory, that can create ResourceSets. This solves many problems using EMF in pure OSGi. There is also a Thread-safe ResourceSet implementation regarding the usage of Resources

https://gitlab.com/gecko.io/geckoEMF

Mark

Am 11.03.20 um 13:26 schrieb Alain Picard via osgi-dev:
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 <mailto: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 <mailto: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 <mailto: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 <mailto:pic...@castortech.com>
        www.castortech.com <http://www.castortech.com/>


        On Mon, Mar 2, 2020 at 3:40 AM Tim Ward <tim.w...@paremus.com
        <mailto: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 <mailto: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 <mailto:osgi-dev@mail.osgi.org>
            https://mail.osgi.org/mailman/listinfo/osgi-dev

    _______________________________________________
    OSGi Developer Mail List
    osgi-dev@mail.osgi.org <mailto: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

--
Mark Hoffmann
M.A. Dipl.-Betriebswirt (FH)
Geschäftsführer

Tel:    +49 3641 384 910 0
Mobil:  +49 175 701 2201
E-Mail: m.hoffm...@data-in-motion.biz
Web: www.datainmotion.de

Data In Motion Consulting GmbH
Kahlaische Straße 4
07745 Jena

Geschäftsführer
Mark Hoffmann
Jürgen Albert

Jena HRB 513025
Steuernummer 162/107/05779
USt-Id DE310002614


_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to