You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (JIRA)" <ji...@apache.org> on 2018/02/26 13:09:00 UTC

[jira] [Updated] (CAMEL-11810) Lifecycle problems for services retrieved from Blueprint container

     [ https://issues.apache.org/jira/browse/CAMEL-11810?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Claus Ibsen updated CAMEL-11810:
--------------------------------
    Fix Version/s:     (was: 2.21.0)
                   2.22.0

> Lifecycle problems for services retrieved from Blueprint container
> ------------------------------------------------------------------
>
>                 Key: CAMEL-11810
>                 URL: https://issues.apache.org/jira/browse/CAMEL-11810
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-blueprint
>            Reporter: Grzegorz Grzybek
>            Assignee: Grzegorz Grzybek
>            Priority: Major
>             Fix For: 2.22.0
>
>
> I have a case where one bundle/blueprint-container defines:
> {code:xml}
>     <bean id="messageIdRepositoryImpl" class="org.apache.camel.processor.idempotent.MemoryIdempotentRepository"/>
>     <service id="messageIdRepository" interface="org.apache.camel.spi.IdempotentRepository" ref="messageIdRepositoryImpl" />
> {code}
> and another one defines Camel context with:
> {code:xml}
>     <reference id="messageIdRepository" interface="org.apache.camel.spi.IdempotentRepository"/>
>     <camelContext xmlns="http://camel.apache.org/schema/blueprint">
>         <route id="xx">
>             <from uri="file://xxx?y=z&amp;readLock=idempotent&amp;idempotent=true&amp;idempotentRepository=#messageIdRepository&amp;other.properties[...]" />
> {code}
> The problem is that when bundle defining {{messageIdRepositoryImpl}} is stopped, stopping bundle/blueprint-container with camel context that references {{messageIdRepositoryImpl}} leads to wait on Proxy/ReferenceRecipe:
> {noformat}
> org.osgi.service.blueprint.container.ServiceUnavailableException: Timeout expired when waiting for mandatory OSGi service reference: (objectClass=org.apache.camel.spi.IdempotentRepository)
> 	at org.apache.aries.blueprint.container.ReferenceRecipe.getService(ReferenceRecipe.java:234)
> 	at org.apache.aries.blueprint.container.ReferenceRecipe.access$000(ReferenceRecipe.java:56)
> 	at org.apache.aries.blueprint.container.ReferenceRecipe$ServiceDispatcher.call(ReferenceRecipe.java:306)
> 	at Proxy28f0d520_9465_4682_9ec1_02ae44e9fa4a.toString(Unknown Source)
> 	at java.lang.String.valueOf(String.java:2994)[:1.8.0_144]
> 	at java.lang.StringBuilder.append(StringBuilder.java:131)[:1.8.0_144]
> 	at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3214)
> 	at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3234)
> 	at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3222)
> 	at org.apache.camel.impl.DefaultCamelContext.doStop(DefaultCamelContext.java:3101)
> 	at org.apache.camel.support.ServiceSupport.stop(ServiceSupport.java:102)
> 	at org.apache.camel.blueprint.BlueprintCamelContext.destroy(BlueprintCamelContext.java:129)
> ...
> {noformat}
> There are few problems here. First - {{GenericFileEndpoint.doStart()}} does this:
> {code:java}
> if (idempotentRepository != null) {
>     getCamelContext().addService(idempotentRepository, true);
> }
> {code}
> which adds the blueprint recipe (proxy) to {{org.apache.camel.impl.DefaultCamelContext#servicesToStop}} without a way to specify {{stopOnShutdown=false}}.
> IMO services obtained from OSGi registry should not be tied to lifecycle of single context with route having {{#referenceToOsgiOrBlueprintService}} in endpoint URI.
> Also - the above stack trace is not retrieved when stopping an osgi service, but when log.warning an exception!:
> {code:xml}
> log.warn("Error occurred while shutting down service: " + service + ". This exception will be ignored.", e);
> {code}
> In the above code we have implicit {{toString()}} call on service which leads to another proxy call which calls {{org.apache.aries.blueprint.container.ReferenceRecipe.ServiceDispatcher#call()}} → {{org.apache.aries.blueprint.container.ReferenceRecipe#getService()}} → {{org.apache.aries.blueprint.container.ReferenceRecipe#monitor.wait(metadata.getTimeout()}}.
> The most obvious fix is to move idempotent repository to a blueprint file where file endpoint is used.
> But as OSGi devil's advocate, I suggest more generic solution: when looking up objects inside {{org.apache.camel.blueprint.BlueprintContainerRegistry}}, in addition to calling {{org.osgi.service.blueprint.container.BlueprintContainer#getComponentInstance()}} we may check if {{blueprintContainer.getComponentMetadata(name) instanceof ReferenceMetadata}} and in such case return a proxied proxy that would prevent waiting for blueprint reference when we're stopping the context - we'd have to check if the target service is available anyway (why ReferenceRecipe doesn't have a method like "tryGetService()"?)...
> Less generic fix could be to add a flag used instead of default:
> {code:java}
> // idempotent repository may be used by others, so add it as a service so its stopped when CamelContext stops
> if (idempotentRepository != null) {
>     getCamelContext().addService(idempotentRepository, true);
> }
> {code}
> so user could decide whether idempotent repository is or isn't "external" ("shared").



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)