Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
None
-
None
-
Unknown
Description
When the org.apache.camel.impl.ProducerCache doGetProducer method is called from org.apache.camel.processor.SendProcessor's doStart() method, it will create new instance of a Producer, and put it into Camel context by calling getCamelContext().addService(answer, false);. However, it will not put the object into producers or the pool map, because it is not ServicePoolAware and is not a singleton. This results in a service that will later be started by DeferServiceStartupListener and will stay started until the whole context is closed.
protected synchronized Producer doGetProducer(Endpoint endpoint, boolean pooled) { String key = endpoint.getEndpointUri(); Producer answer = producers.get(key); if (pooled && answer == null) { // try acquire from connection pool answer = pool.acquire(endpoint); } if (answer == null) { // create a new producer try { answer = endpoint.createProducer(); // add as service which will also start the service // (false => we and handling the lifecycle of the producer in this cache) getCamelContext().addService(answer, false); } catch (Throwable e) { throw new FailedToCreateProducerException(endpoint, e); } // add producer to cache or pool if applicable if (pooled && answer instanceof ServicePoolAware) { LOG.debug("Adding to producer service pool with key: {} for producer: {}", endpoint, answer); answer = pool.addAndAcquire(endpoint, answer); } else if (answer.isSingleton()) { LOG.debug("Adding to producer cache with key: {} for producer: {}", endpoint, answer); producers.put(key, answer); } } if (answer != null) { // record statistics if (extendedStatistics) { statistics.onHit(key); } } return answer; }
Here is the part of doStart() method from SendProcessor class. The producer is acquired and after that is immediately released in ProducerCache, however it is not removed from Camel context and stays there as a Service and will later by started by DeferServiceStartupListener
Producer producer = producerCache.acquireProducer(destination); if (producer instanceof ServicePoolAware || !producer.isSingleton()) { // no we cannot optimize it - so release the producer back to the producer cache // and use the producer cache for sending producerCache.releaseProducer(destination, producer); } else { // yes we can optimize and use the producer directly for sending this.producer = AsyncProcessorConverterHelper.convert(producer); }