Uploaded image for project: 'Camel'
  1. Camel
  2. CAMEL-12131

CacheProducer should not put services in Camel context, that are not singletons and are not ServicePoolAware

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • None
    • 2.19.5, 2.20.2, 2.21.0
    • camel-core
    • 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);
              }
      

      Attachments

        Activity

          People

            davsclaus Claus Ibsen
            rgala Rafał Gała
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: