You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by zr...@apache.org on 2020/12/18 11:17:49 UTC

[camel] branch issue/CAMEL-12871 updated (9c03a38 -> e1760b1)

This is an automated email from the ASF dual-hosted git repository.

zregvart pushed a change to branch issue/CAMEL-12871
in repository https://gitbox.apache.org/repos/asf/camel.git.


    omit 9c03a38  CAMEL-12871: disconnect on handshake failure
    omit 646eec0  CAMEL-12871: release resources on stop
    omit e91720f  CAMEL-12871: stub server and test
     add bdc89d2  Support service account authentication (#4783)
     add 1a7c4d6  Regen
     add 2aa9c14  CAMEL-15959: Add security label to options
     add 2276b49  change ? to & (#4761)
     add 25350489 change ? to &
     add 7c5ac14  Upgrade AWS SDK v2 to version 2.15.48
     add dd24454  Regen and sync deps
     add b1c4bba  Switch camel-dependencies to 3.8.0-SNAPSHOT
     add a1e5195  Regen for commit dd244543fa3472112c24e042cd032cdae8ce473f
     add 2e0456e  CAMEL-15956: camel-core - Deprecate init switch as its not in use.
     add b7306bc  prepare for next release
     add 67204f9  Upgrade Zipkin to version 2.23.1
     add e657318  Upgrade Zipkin Reporter to version 2.16.2
     add a2ce9dd  Sync deps
     add be27bd0  camel-core - Reorder type converter to better match correct
     add 055fb3f  Added test based on user forum issue
     add e530614  CAMEL-15938: camel-aws-iam - operation is not always required as parameter.
     add 45247f0  Regen for commit e53061441921f4e9a5cd145f3fe6664dba6fa68d
     add 75edd58  CAMEL-13024: camel-mail - Add option to configure whether to encode attachment file name or not. Thanks to Stephan Siano for unit test.
     add 73de6c5  Regen for commit 75edd58d225883fb5e50b700b8108512103851d9 (#4792)
     add a264adb  CAMEL-15290: camel-cxf - RS producer should not leak over HTTP headers from org.apache.cxf when sending to REST server.
     add 3b0fda1  Upgrade AWS SDK v2 to version 2.15.49
     add 93d42d9  Sync deps and regen
     add 387b4b7  Upgrade Netty to version 4.1.56.Final
     add 333ab60  Sync deps
     add e61fb46  Regen for commit 93d42d96a325f15760fb3bfc2f47a0e1a0c8d4c4
     add 2152f30  Upgrade Braintree Java to version 3.5.0
     add a21d0d1  Sync deps
     add a1f2954  Upgrade OWASP Maven plugin to version 6.0.3
     add b377bc8  Sync deps
     add 5e805e3  Regen for commit b377bc8cca9ab62a723c86cc18a71e13622ad22c
     add ddf8afc  CAMEL-15969 - Camel-AWS2-SNS: Set the topic policy as file and not as plain String
     add bde2d5b  CAMEL-15969 - Fixed test and add file policy
     add 23d77e0  CAMEL-15969 - Regen catalog
     add 06fa1d8  CAMEL-15969 - Added a note about the policy option
     new 5f1e7e9  CAMEL-12871: stub server and test
     new 2fada10  CAMEL-12871: release resources on stop
     new e1760b1  CAMEL-12871: disconnect on handshake failure

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (9c03a38)
            \
             N -- N -- N   refs/heads/issue/CAMEL-12871 (e1760b1)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 camel-dependencies/pom.xml                         |  14 +-
 .../apache/camel/catalog/components/activemq.json  |   2 +-
 .../apache/camel/catalog/components/ahc-ws.json    |   2 +-
 .../apache/camel/catalog/components/ahc-wss.json   |   2 +-
 .../org/apache/camel/catalog/components/ahc.json   |   2 +-
 .../org/apache/camel/catalog/components/amqp.json  |   2 +-
 .../org/apache/camel/catalog/components/apns.json  |   2 +-
 .../apache/camel/catalog/components/arangodb.json  |   2 +-
 .../org/apache/camel/catalog/components/as2.json   |   2 +-
 .../apache/camel/catalog/components/asterisk.json  |   2 +-
 .../apache/camel/catalog/components/atlasmap.json  |   2 +-
 .../org/apache/camel/catalog/components/atmos.json |   2 +-
 .../catalog/components/atmosphere-websocket.json   |   2 +-
 .../org/apache/camel/catalog/components/atom.json  |   2 +-
 .../camel/catalog/components/atomix-map.json       |   2 +-
 .../camel/catalog/components/atomix-messaging.json |   2 +-
 .../camel/catalog/components/atomix-multimap.json  |   2 +-
 .../camel/catalog/components/atomix-queue.json     |   2 +-
 .../camel/catalog/components/atomix-set.json       |   2 +-
 .../camel/catalog/components/atomix-value.json     |   2 +-
 .../org/apache/camel/catalog/components/avro.json  |   2 +-
 .../apache/camel/catalog/components/aws-cw.json    |   2 +-
 .../apache/camel/catalog/components/aws-ddb.json   |   2 +-
 .../camel/catalog/components/aws-ddbstream.json    |   2 +-
 .../apache/camel/catalog/components/aws-ec2.json   |   2 +-
 .../apache/camel/catalog/components/aws-ecs.json   |   2 +-
 .../apache/camel/catalog/components/aws-eks.json   |   2 +-
 .../apache/camel/catalog/components/aws-iam.json   |   2 +-
 .../catalog/components/aws-kinesis-firehose.json   |   2 +-
 .../camel/catalog/components/aws-kinesis.json      |   2 +-
 .../apache/camel/catalog/components/aws-kms.json   |   2 +-
 .../camel/catalog/components/aws-lambda.json       |   2 +-
 .../apache/camel/catalog/components/aws-mq.json    |   2 +-
 .../apache/camel/catalog/components/aws-msk.json   |   2 +-
 .../apache/camel/catalog/components/aws-s3.json    |   2 +-
 .../apache/camel/catalog/components/aws-sdb.json   |   2 +-
 .../apache/camel/catalog/components/aws-ses.json   |   2 +-
 .../apache/camel/catalog/components/aws-sns.json   |   2 +-
 .../apache/camel/catalog/components/aws-sqs.json   |   2 +-
 .../apache/camel/catalog/components/aws-swf.json   |   2 +-
 .../camel/catalog/components/aws-translate.json    |   2 +-
 .../camel/catalog/components/aws2-athena.json      |   2 +-
 .../apache/camel/catalog/components/aws2-cw.json   |   2 +-
 .../apache/camel/catalog/components/aws2-ddb.json  |   2 +-
 .../camel/catalog/components/aws2-ddbstream.json   |   2 +-
 .../apache/camel/catalog/components/aws2-ec2.json  |   2 +-
 .../apache/camel/catalog/components/aws2-ecs.json  |   2 +-
 .../apache/camel/catalog/components/aws2-eks.json  |   2 +-
 .../apache/camel/catalog/components/aws2-iam.json  |   6 +-
 .../catalog/components/aws2-kinesis-firehose.json  |   2 +-
 .../camel/catalog/components/aws2-kinesis.json     |   2 +-
 .../apache/camel/catalog/components/aws2-kms.json  |   2 +-
 .../camel/catalog/components/aws2-lambda.json      |   2 +-
 .../apache/camel/catalog/components/aws2-mq.json   |   2 +-
 .../apache/camel/catalog/components/aws2-msk.json  |   2 +-
 .../apache/camel/catalog/components/aws2-s3.json   |   2 +-
 .../apache/camel/catalog/components/aws2-ses.json  |   2 +-
 .../apache/camel/catalog/components/aws2-sns.json  |   6 +-
 .../apache/camel/catalog/components/aws2-sqs.json  |   2 +-
 .../apache/camel/catalog/components/aws2-sts.json  |   2 +-
 .../camel/catalog/components/aws2-translate.json   |   2 +-
 .../camel/catalog/components/azure-blob.json       |   2 +-
 .../camel/catalog/components/azure-eventhubs.json  |   2 +-
 .../camel/catalog/components/azure-queue.json      |   2 +-
 .../catalog/components/azure-storage-blob.json     |   2 +-
 .../catalog/components/azure-storage-queue.json    |   2 +-
 .../camel/catalog/components/bean-validator.json   |   2 +-
 .../org/apache/camel/catalog/components/bean.json  |   2 +-
 .../apache/camel/catalog/components/beanstalk.json |   2 +-
 .../apache/camel/catalog/components/bonita.json    |   2 +-
 .../org/apache/camel/catalog/components/box.json   |   2 +-
 .../apache/camel/catalog/components/braintree.json |   2 +-
 .../apache/camel/catalog/components/browse.json    |   2 +-
 .../camel/catalog/components/caffeine-cache.json   |   2 +-
 .../catalog/components/caffeine-loadcache.json     |   2 +-
 .../camel/catalog/components/chatscript.json       |   2 +-
 .../org/apache/camel/catalog/components/chunk.json |   2 +-
 .../org/apache/camel/catalog/components/class.json |   2 +-
 .../apache/camel/catalog/components/cm-sms.json    |   2 +-
 .../org/apache/camel/catalog/components/cmis.json  |   2 +-
 .../apache/camel/catalog/components/coap+tcp.json  |   2 +-
 .../org/apache/camel/catalog/components/coap.json  |   2 +-
 .../apache/camel/catalog/components/coaps+tcp.json |   2 +-
 .../org/apache/camel/catalog/components/coaps.json |   2 +-
 .../apache/camel/catalog/components/cometd.json    |   2 +-
 .../apache/camel/catalog/components/cometds.json   |   2 +-
 .../apache/camel/catalog/components/consul.json    |   2 +-
 .../camel/catalog/components/controlbus.json       |   2 +-
 .../org/apache/camel/catalog/components/corda.json |   2 +-
 .../apache/camel/catalog/components/couchbase.json |   2 +-
 .../apache/camel/catalog/components/couchdb.json   |   2 +-
 .../org/apache/camel/catalog/components/cql.json   |   2 +-
 .../org/apache/camel/catalog/components/cron.json  |   2 +-
 .../camel/catalog/components/crypto-cms.json       |   2 +-
 .../apache/camel/catalog/components/crypto.json    |   2 +-
 .../org/apache/camel/catalog/components/cxf.json   |   2 +-
 .../org/apache/camel/catalog/components/cxfrs.json |   2 +-
 .../camel/catalog/components/dataformat.json       |   2 +-
 .../camel/catalog/components/dataset-test.json     |   2 +-
 .../apache/camel/catalog/components/dataset.json   |   2 +-
 .../camel/catalog/components/debezium-mongodb.json |   2 +-
 .../camel/catalog/components/debezium-mysql.json   |   2 +-
 .../catalog/components/debezium-postgres.json      |   2 +-
 .../catalog/components/debezium-sqlserver.json     |   2 +-
 .../camel/catalog/components/digitalocean.json     |   2 +-
 .../apache/camel/catalog/components/direct-vm.json |   2 +-
 .../apache/camel/catalog/components/direct.json    |   2 +-
 .../camel/catalog/components/disruptor-vm.json     |   2 +-
 .../apache/camel/catalog/components/disruptor.json |   2 +-
 .../org/apache/camel/catalog/components/djl.json   |   2 +-
 .../org/apache/camel/catalog/components/dns.json   |   2 +-
 .../apache/camel/catalog/components/docker.json    |   2 +-
 .../org/apache/camel/catalog/components/dozer.json |   2 +-
 .../org/apache/camel/catalog/components/drill.json |   2 +-
 .../apache/camel/catalog/components/dropbox.json   |   2 +-
 .../apache/camel/catalog/components/ehcache.json   |   2 +-
 .../catalog/components/elasticsearch-rest.json     |   2 +-
 .../org/apache/camel/catalog/components/elsql.json |   2 +-
 .../apache/camel/catalog/components/etcd-keys.json |   2 +-
 .../camel/catalog/components/etcd-stats.json       |   2 +-
 .../camel/catalog/components/etcd-watch.json       |   2 +-
 .../org/apache/camel/catalog/components/exec.json  |   2 +-
 .../apache/camel/catalog/components/facebook.json  |   2 +-
 .../org/apache/camel/catalog/components/fhir.json  |   2 +-
 .../camel/catalog/components/file-watch.json       |   2 +-
 .../org/apache/camel/catalog/components/file.json  |   2 +-
 .../apache/camel/catalog/components/flatpack.json  |   2 +-
 .../org/apache/camel/catalog/components/flink.json |   2 +-
 .../org/apache/camel/catalog/components/fop.json   |   2 +-
 .../camel/catalog/components/freemarker.json       |   2 +-
 .../org/apache/camel/catalog/components/ftp.json   |   2 +-
 .../org/apache/camel/catalog/components/ftps.json  |   2 +-
 .../apache/camel/catalog/components/ganglia.json   |   2 +-
 .../apache/camel/catalog/components/geocoder.json  |   2 +-
 .../org/apache/camel/catalog/components/git.json   |   2 +-
 .../apache/camel/catalog/components/github.json    |   2 +-
 .../catalog/components/google-bigquery-sql.json    |   2 +-
 .../camel/catalog/components/google-bigquery.json  |   2 +-
 .../catalog/components/google-calendar-stream.json |  12 +-
 .../camel/catalog/components/google-calendar.json  |  18 +-
 .../camel/catalog/components/google-drive.json     |   2 +-
 .../catalog/components/google-mail-stream.json     |   2 +-
 .../camel/catalog/components/google-mail.json      |   2 +-
 .../camel/catalog/components/google-pubsub.json    |   2 +-
 .../catalog/components/google-sheets-stream.json   |   2 +-
 .../camel/catalog/components/google-sheets.json    |   2 +-
 .../org/apache/camel/catalog/components/gora.json  |   2 +-
 .../org/apache/camel/catalog/components/grape.json |   2 +-
 .../apache/camel/catalog/components/graphql.json   |   2 +-
 .../org/apache/camel/catalog/components/grpc.json  |   2 +-
 .../camel/catalog/components/guava-eventbus.json   |   2 +-
 .../catalog/components/hazelcast-atomicvalue.json  |   2 +-
 .../catalog/components/hazelcast-instance.json     |   2 +-
 .../camel/catalog/components/hazelcast-list.json   |   2 +-
 .../camel/catalog/components/hazelcast-map.json    |   2 +-
 .../catalog/components/hazelcast-multimap.json     |   2 +-
 .../camel/catalog/components/hazelcast-queue.json  |   2 +-
 .../components/hazelcast-replicatedmap.json        |   2 +-
 .../catalog/components/hazelcast-ringbuffer.json   |   2 +-
 .../camel/catalog/components/hazelcast-seda.json   |   2 +-
 .../camel/catalog/components/hazelcast-set.json    |   2 +-
 .../camel/catalog/components/hazelcast-topic.json  |   2 +-
 .../org/apache/camel/catalog/components/hbase.json |   2 +-
 .../org/apache/camel/catalog/components/hdfs.json  |   2 +-
 .../org/apache/camel/catalog/components/http.json  |   2 +-
 .../org/apache/camel/catalog/components/https.json |   2 +-
 .../camel/catalog/components/iec60870-client.json  |   2 +-
 .../camel/catalog/components/iec60870-server.json  |   2 +-
 .../camel/catalog/components/ignite-cache.json     |   2 +-
 .../camel/catalog/components/ignite-compute.json   |   2 +-
 .../camel/catalog/components/ignite-events.json    |   2 +-
 .../camel/catalog/components/ignite-idgen.json     |   2 +-
 .../camel/catalog/components/ignite-messaging.json |   2 +-
 .../camel/catalog/components/ignite-queue.json     |   2 +-
 .../camel/catalog/components/ignite-set.json       |   2 +-
 .../org/apache/camel/catalog/components/imap.json  |   4 +-
 .../org/apache/camel/catalog/components/imaps.json |   4 +-
 .../camel/catalog/components/infinispan.json       |   2 +-
 .../apache/camel/catalog/components/influxdb.json  |   2 +-
 .../org/apache/camel/catalog/components/iota.json  |   2 +-
 .../org/apache/camel/catalog/components/ipfs.json  |   2 +-
 .../org/apache/camel/catalog/components/irc.json   |   2 +-
 .../apache/camel/catalog/components/ironmq.json    |   2 +-
 .../org/apache/camel/catalog/components/jbpm.json  |   2 +-
 .../apache/camel/catalog/components/jcache.json    |   2 +-
 .../apache/camel/catalog/components/jclouds.json   |   2 +-
 .../org/apache/camel/catalog/components/jcr.json   |   2 +-
 .../org/apache/camel/catalog/components/jdbc.json  |   2 +-
 .../org/apache/camel/catalog/components/jetty.json |   2 +-
 .../camel/catalog/components/jgroups-raft.json     |   2 +-
 .../apache/camel/catalog/components/jgroups.json   |   2 +-
 .../org/apache/camel/catalog/components/jing.json  |   2 +-
 .../org/apache/camel/catalog/components/jira.json  |   2 +-
 .../org/apache/camel/catalog/components/jms.json   |   2 +-
 .../org/apache/camel/catalog/components/jmx.json   |   2 +-
 .../org/apache/camel/catalog/components/jolt.json  |   2 +-
 .../org/apache/camel/catalog/components/jooq.json  |   2 +-
 .../org/apache/camel/catalog/components/jpa.json   |   2 +-
 .../org/apache/camel/catalog/components/jslt.json  |   2 +-
 .../camel/catalog/components/json-validator.json   |   2 +-
 .../apache/camel/catalog/components/jsonata.json   |   2 +-
 .../org/apache/camel/catalog/components/jt400.json |   2 +-
 .../org/apache/camel/catalog/components/kafka.json |   2 +-
 .../catalog/components/kubernetes-config-maps.json |   2 +-
 .../components/kubernetes-custom-resources.json    |   2 +-
 .../catalog/components/kubernetes-deployments.json |   2 +-
 .../camel/catalog/components/kubernetes-hpa.json   |   2 +-
 .../camel/catalog/components/kubernetes-job.json   |   2 +-
 .../catalog/components/kubernetes-namespaces.json  |   2 +-
 .../camel/catalog/components/kubernetes-nodes.json |   2 +-
 .../kubernetes-persistent-volumes-claims.json      |   2 +-
 .../components/kubernetes-persistent-volumes.json  |   2 +-
 .../camel/catalog/components/kubernetes-pods.json  |   2 +-
 .../kubernetes-replication-controllers.json        |   2 +-
 .../components/kubernetes-resources-quota.json     |   2 +-
 .../catalog/components/kubernetes-secrets.json     |   2 +-
 .../components/kubernetes-service-accounts.json    |   2 +-
 .../catalog/components/kubernetes-services.json    |   2 +-
 .../org/apache/camel/catalog/components/kudu.json  |   2 +-
 .../apache/camel/catalog/components/language.json  |   2 +-
 .../org/apache/camel/catalog/components/ldap.json  |   2 +-
 .../org/apache/camel/catalog/components/ldif.json  |   2 +-
 .../org/apache/camel/catalog/components/log.json   |   2 +-
 .../org/apache/camel/catalog/components/lpr.json   |   2 +-
 .../apache/camel/catalog/components/lucene.json    |   2 +-
 .../camel/catalog/components/lumberjack.json       |   2 +-
 .../apache/camel/catalog/components/master.json    |   2 +-
 .../apache/camel/catalog/components/metrics.json   |   2 +-
 .../camel/catalog/components/micrometer.json       |   2 +-
 .../catalog/components/microprofile-metrics.json   |   2 +-
 .../camel/catalog/components/milo-client.json      |   2 +-
 .../camel/catalog/components/milo-server.json      |   2 +-
 .../org/apache/camel/catalog/components/mina.json  |   2 +-
 .../org/apache/camel/catalog/components/minio.json |   2 +-
 .../org/apache/camel/catalog/components/mllp.json  |   2 +-
 .../org/apache/camel/catalog/components/mock.json  |   2 +-
 .../camel/catalog/components/mongodb-gridfs.json   |   2 +-
 .../apache/camel/catalog/components/mongodb.json   |   2 +-
 .../org/apache/camel/catalog/components/msv.json   |   2 +-
 .../apache/camel/catalog/components/mustache.json  |   2 +-
 .../org/apache/camel/catalog/components/mvel.json  |   2 +-
 .../camel/catalog/components/mybatis-bean.json     |   2 +-
 .../apache/camel/catalog/components/mybatis.json   |   2 +-
 .../apache/camel/catalog/components/nagios.json    |   2 +-
 .../org/apache/camel/catalog/components/nats.json  |   2 +-
 .../camel/catalog/components/netty-http.json       |   2 +-
 .../org/apache/camel/catalog/components/netty.json |   2 +-
 .../apache/camel/catalog/components/nitrite.json   |   2 +-
 .../org/apache/camel/catalog/components/nsq.json   |   2 +-
 .../apache/camel/catalog/components/oaipmh.json    |   2 +-
 .../apache/camel/catalog/components/olingo2.json   |   2 +-
 .../apache/camel/catalog/components/olingo4.json   |   2 +-
 .../components/openshift-build-configs.json        |   2 +-
 .../camel/catalog/components/openshift-builds.json |   2 +-
 .../camel/catalog/components/openstack-cinder.json |   2 +-
 .../camel/catalog/components/openstack-glance.json |   2 +-
 .../catalog/components/openstack-keystone.json     |   2 +-
 .../catalog/components/openstack-neutron.json      |   2 +-
 .../camel/catalog/components/openstack-nova.json   |   2 +-
 .../camel/catalog/components/openstack-swift.json  |   2 +-
 .../camel/catalog/components/optaplanner.json      |   2 +-
 .../org/apache/camel/catalog/components/paho.json  |   2 +-
 .../org/apache/camel/catalog/components/pdf.json   |   2 +-
 .../catalog/components/pg-replication-slot.json    |   2 +-
 .../apache/camel/catalog/components/pgevent.json   |   2 +-
 .../camel/catalog/components/platform-http.json    |   2 +-
 .../org/apache/camel/catalog/components/pop3.json  |   4 +-
 .../org/apache/camel/catalog/components/pop3s.json |   4 +-
 .../apache/camel/catalog/components/pubnub.json    |   2 +-
 .../apache/camel/catalog/components/pulsar.json    |   2 +-
 .../apache/camel/catalog/components/quartz.json    |   2 +-
 .../apache/camel/catalog/components/quickfix.json  |   2 +-
 .../apache/camel/catalog/components/rabbitmq.json  |   2 +-
 .../camel/catalog/components/reactive-streams.json |   2 +-
 .../org/apache/camel/catalog/components/ref.json   |   2 +-
 .../apache/camel/catalog/components/rest-api.json  |   2 +-
 .../camel/catalog/components/rest-openapi.json     |   2 +-
 .../camel/catalog/components/rest-swagger.json     |   2 +-
 .../org/apache/camel/catalog/components/rest.json  |   2 +-
 .../apache/camel/catalog/components/resteasy.json  |   2 +-
 .../camel/catalog/components/robotframework.json   |   2 +-
 .../org/apache/camel/catalog/components/rss.json   |   2 +-
 .../org/apache/camel/catalog/components/saga.json  |   2 +-
 .../camel/catalog/components/salesforce.json       |   2 +-
 .../camel/catalog/components/sap-netweaver.json    |   2 +-
 .../apache/camel/catalog/components/scheduler.json |   2 +-
 .../camel/catalog/components/schematron.json       |   2 +-
 .../org/apache/camel/catalog/components/scp.json   |   2 +-
 .../org/apache/camel/catalog/components/seda.json  |   2 +-
 .../apache/camel/catalog/components/service.json   |   2 +-
 .../camel/catalog/components/servicenow.json       |   2 +-
 .../apache/camel/catalog/components/servlet.json   |   2 +-
 .../org/apache/camel/catalog/components/sftp.json  |   2 +-
 .../org/apache/camel/catalog/components/sip.json   |   2 +-
 .../org/apache/camel/catalog/components/sips.json  |   2 +-
 .../camel/catalog/components/sjms-batch.json       |   2 +-
 .../org/apache/camel/catalog/components/sjms.json  |   2 +-
 .../org/apache/camel/catalog/components/sjms2.json |   2 +-
 .../org/apache/camel/catalog/components/slack.json |   2 +-
 .../org/apache/camel/catalog/components/smpp.json  |   2 +-
 .../org/apache/camel/catalog/components/smpps.json |   2 +-
 .../org/apache/camel/catalog/components/smtp.json  |   4 +-
 .../org/apache/camel/catalog/components/smtps.json |   4 +-
 .../org/apache/camel/catalog/components/snmp.json  |   2 +-
 .../org/apache/camel/catalog/components/solr.json  |   2 +-
 .../apache/camel/catalog/components/solrCloud.json |   2 +-
 .../org/apache/camel/catalog/components/solrs.json |   2 +-
 .../apache/camel/catalog/components/soroush.json   |   2 +-
 .../org/apache/camel/catalog/components/spark.json |   2 +-
 .../camel/catalog/components/splunk-hec.json       |   2 +-
 .../apache/camel/catalog/components/splunk.json    |   2 +-
 .../camel/catalog/components/spring-batch.json     |   2 +-
 .../camel/catalog/components/spring-event.json     |   2 +-
 .../catalog/components/spring-integration.json     |   2 +-
 .../camel/catalog/components/spring-ldap.json      |   2 +-
 .../camel/catalog/components/spring-redis.json     |   2 +-
 .../apache/camel/catalog/components/spring-ws.json |   2 +-
 .../camel/catalog/components/sql-stored.json       |   2 +-
 .../org/apache/camel/catalog/components/sql.json   |   2 +-
 .../org/apache/camel/catalog/components/ssh.json   |   2 +-
 .../org/apache/camel/catalog/components/stax.json  |   2 +-
 .../org/apache/camel/catalog/components/stomp.json |   2 +-
 .../apache/camel/catalog/components/stream.json    |   2 +-
 .../camel/catalog/components/string-template.json  |   2 +-
 .../org/apache/camel/catalog/components/stub.json  |   2 +-
 .../apache/camel/catalog/components/telegram.json  |   2 +-
 .../apache/camel/catalog/components/thrift.json    |   2 +-
 .../org/apache/camel/catalog/components/tika.json  |   2 +-
 .../org/apache/camel/catalog/components/timer.json |   2 +-
 .../apache/camel/catalog/components/twilio.json    |   2 +-
 .../catalog/components/twitter-directmessage.json  |   2 +-
 .../camel/catalog/components/twitter-search.json   |   2 +-
 .../camel/catalog/components/twitter-timeline.json |   2 +-
 .../apache/camel/catalog/components/undertow.json  |   2 +-
 .../apache/camel/catalog/components/validator.json |   2 +-
 .../apache/camel/catalog/components/velocity.json  |   2 +-
 .../camel/catalog/components/vertx-http.json       |   2 +-
 .../camel/catalog/components/vertx-kafka.json      |   2 +-
 .../camel/catalog/components/vertx-websocket.json  |   2 +-
 .../org/apache/camel/catalog/components/vertx.json |   2 +-
 .../org/apache/camel/catalog/components/vm.json    |   2 +-
 .../apache/camel/catalog/components/weather.json   |   2 +-
 .../org/apache/camel/catalog/components/web3j.json |   2 +-
 .../apache/camel/catalog/components/webhook.json   |   2 +-
 .../camel/catalog/components/websocket-jsr356.json |   2 +-
 .../apache/camel/catalog/components/websocket.json |   2 +-
 .../org/apache/camel/catalog/components/weka.json  |   2 +-
 .../apache/camel/catalog/components/wordpress.json |   2 +-
 .../apache/camel/catalog/components/workday.json   |   2 +-
 .../apache/camel/catalog/components/xchange.json   |   2 +-
 .../org/apache/camel/catalog/components/xj.json    |   2 +-
 .../camel/catalog/components/xmlsecurity-sign.json |   2 +-
 .../catalog/components/xmlsecurity-verify.json     |   2 +-
 .../org/apache/camel/catalog/components/xmpp.json  |   2 +-
 .../apache/camel/catalog/components/xquery.json    |   2 +-
 .../camel/catalog/components/xslt-saxon.json       |   2 +-
 .../org/apache/camel/catalog/components/xslt.json  |   2 +-
 .../apache/camel/catalog/components/yammer.json    |   2 +-
 .../apache/camel/catalog/components/zendesk.json   |   2 +-
 .../camel/catalog/components/zookeeper-master.json |   2 +-
 .../apache/camel/catalog/components/zookeeper.json |   2 +-
 .../apache/camel/catalog/dataformats/any23.json    |   2 +-
 .../org/apache/camel/catalog/dataformats/asn1.json |   2 +-
 .../org/apache/camel/catalog/dataformats/avro.json |   2 +-
 .../apache/camel/catalog/dataformats/barcode.json  |   2 +-
 .../apache/camel/catalog/dataformats/base64.json   |   2 +-
 .../apache/camel/catalog/dataformats/beanio.json   |   2 +-
 .../camel/catalog/dataformats/bindy-csv.json       |   2 +-
 .../camel/catalog/dataformats/bindy-fixed.json     |   2 +-
 .../camel/catalog/dataformats/bindy-kvp.json       |   2 +-
 .../org/apache/camel/catalog/dataformats/cbor.json |   2 +-
 .../apache/camel/catalog/dataformats/crypto.json   |   2 +-
 .../org/apache/camel/catalog/dataformats/csv.json  |   2 +-
 .../apache/camel/catalog/dataformats/fhirJson.json |   2 +-
 .../apache/camel/catalog/dataformats/fhirXml.json  |   2 +-
 .../apache/camel/catalog/dataformats/flatpack.json |   2 +-
 .../org/apache/camel/catalog/dataformats/grok.json |   2 +-
 .../camel/catalog/dataformats/gzipdeflater.json    |   2 +-
 .../org/apache/camel/catalog/dataformats/hl7.json  |   2 +-
 .../org/apache/camel/catalog/dataformats/ical.json |   2 +-
 .../camel/catalog/dataformats/jacksonxml.json      |   2 +-
 .../org/apache/camel/catalog/dataformats/jaxb.json |   2 +-
 .../camel/catalog/dataformats/json-fastjson.json   |   2 +-
 .../camel/catalog/dataformats/json-gson.json       |   2 +-
 .../camel/catalog/dataformats/json-jackson.json    |   2 +-
 .../camel/catalog/dataformats/json-johnzon.json    |   2 +-
 .../camel/catalog/dataformats/json-jsonb.json      |   2 +-
 .../camel/catalog/dataformats/json-xstream.json    |   2 +-
 .../apache/camel/catalog/dataformats/jsonApi.json  |   2 +-
 .../org/apache/camel/catalog/dataformats/lzf.json  |   2 +-
 .../camel/catalog/dataformats/mime-multipart.json  |   2 +-
 .../org/apache/camel/catalog/dataformats/pgp.json  |   2 +-
 .../apache/camel/catalog/dataformats/protobuf.json |   2 +-
 .../org/apache/camel/catalog/dataformats/rss.json  |   2 +-
 .../camel/catalog/dataformats/secureXML.json       |   2 +-
 .../apache/camel/catalog/dataformats/soapjaxb.json |   2 +-
 .../apache/camel/catalog/dataformats/syslog.json   |   2 +-
 .../apache/camel/catalog/dataformats/tarfile.json  |   2 +-
 .../apache/camel/catalog/dataformats/thrift.json   |   2 +-
 .../camel/catalog/dataformats/tidyMarkup.json      |   2 +-
 .../camel/catalog/dataformats/univocity-csv.json   |   2 +-
 .../camel/catalog/dataformats/univocity-fixed.json |   2 +-
 .../camel/catalog/dataformats/univocity-tsv.json   |   2 +-
 .../apache/camel/catalog/dataformats/xstream.json  |   2 +-
 .../camel/catalog/dataformats/yaml-snakeyaml.json  |   2 +-
 .../camel/catalog/dataformats/zipdeflater.json     |   2 +-
 .../apache/camel/catalog/dataformats/zipfile.json  |   2 +-
 .../camel/catalog/docs/aws2-iam-component.adoc     |   4 +-
 .../camel/catalog/docs/aws2-sns-component.adoc     |   4 +-
 .../catalog/docs/google-calendar-component.adoc    |  12 +-
 .../docs/google-calendar-stream-component.adoc     |   5 +-
 .../apache/camel/catalog/docs/mail-component.adoc  |   6 +-
 .../camel/catalog/docs/telegram-component.adoc     |   2 +-
 .../org/apache/camel/catalog/languages/bean.json   |   2 +-
 .../apache/camel/catalog/languages/constant.json   |   2 +-
 .../apache/camel/catalog/languages/csimple.json    |   2 +-
 .../apache/camel/catalog/languages/datasonnet.json |   2 +-
 .../camel/catalog/languages/exchangeProperty.json  |   2 +-
 .../org/apache/camel/catalog/languages/file.json   |   2 +-
 .../org/apache/camel/catalog/languages/groovy.json |   2 +-
 .../org/apache/camel/catalog/languages/header.json |   2 +-
 .../apache/camel/catalog/languages/hl7terser.json  |   2 +-
 .../org/apache/camel/catalog/languages/joor.json   |   2 +-
 .../apache/camel/catalog/languages/jsonpath.json   |   2 +-
 .../org/apache/camel/catalog/languages/mvel.json   |   2 +-
 .../org/apache/camel/catalog/languages/ognl.json   |   2 +-
 .../org/apache/camel/catalog/languages/ref.json    |   2 +-
 .../org/apache/camel/catalog/languages/simple.json |   2 +-
 .../org/apache/camel/catalog/languages/spel.json   |   2 +-
 .../apache/camel/catalog/languages/tokenize.json   |   2 +-
 .../org/apache/camel/catalog/languages/xquery.json |   2 +-
 .../apache/camel/catalog/languages/xtokenize.json  |   2 +-
 .../apache/camel/catalog/others/attachments.json   |   2 +-
 .../org/apache/camel/catalog/others/aws-xray.json  |   2 +-
 .../org/apache/camel/catalog/others/cdi.json       |   2 +-
 .../apache/camel/catalog/others/csimple-joor.json  |   2 +-
 .../apache/camel/catalog/others/cxf-transport.json |   2 +-
 .../org/apache/camel/catalog/others/elytron.json   |   2 +-
 .../org/apache/camel/catalog/others/etcd3.json     |   2 +-
 .../apache/camel/catalog/others/headersmap.json    |   2 +-
 .../org/apache/camel/catalog/others/hystrix.json   |   2 +-
 .../org/apache/camel/catalog/others/jasypt.json    |   2 +-
 .../org/apache/camel/catalog/others/jta.json       |   2 +-
 .../camel/catalog/others/leveldb-legacy.json       |   2 +-
 .../org/apache/camel/catalog/others/leveldb.json   |   2 +-
 .../org/apache/camel/catalog/others/lra.json       |   2 +-
 .../camel/catalog/others/microprofile-config.json  |   2 +-
 .../others/microprofile-fault-tolerance.json       |   2 +-
 .../camel/catalog/others/microprofile-health.json  |   2 +-
 .../apache/camel/catalog/others/openapi-java.json  |   2 +-
 .../apache/camel/catalog/others/opentelemetry.json |   2 +-
 .../apache/camel/catalog/others/opentracing.json   |   2 +-
 .../camel/catalog/others/platform-http-vertx.json  |   2 +-
 .../catalog/others/reactive-executor-vertx.json    |   2 +-
 .../org/apache/camel/catalog/others/reactor.json   |   2 +-
 .../org/apache/camel/catalog/others/redis.json     |   2 +-
 .../apache/camel/catalog/others/resilience4j.json  |   2 +-
 .../org/apache/camel/catalog/others/ribbon.json    |   2 +-
 .../org/apache/camel/catalog/others/rxjava.json    |   2 +-
 .../org/apache/camel/catalog/others/shiro.json     |   2 +-
 .../camel/catalog/others/spring-javaconfig.json    |   2 +-
 .../apache/camel/catalog/others/spring-main.json   |   2 +-
 .../camel/catalog/others/spring-security.json      |   2 +-
 .../apache/camel/catalog/others/swagger-java.json  |   2 +-
 .../org/apache/camel/catalog/others/test-cdi.json  |   2 +-
 .../apache/camel/catalog/others/test-junit5.json   |   2 +-
 .../camel/catalog/others/test-spring-junit5.json   |   2 +-
 .../apache/camel/catalog/others/test-spring.json   |   2 +-
 .../org/apache/camel/catalog/others/test.json      |   2 +-
 .../catalog/others/testcontainers-junit5.json      |   2 +-
 .../others/testcontainers-spring-junit5.json       |   2 +-
 .../catalog/others/testcontainers-spring.json      |   2 +-
 .../camel/catalog/others/testcontainers.json       |   2 +-
 .../catalog/others/threadpoolfactory-vertx.json    |   2 +-
 .../org/apache/camel/catalog/others/tracing.json   |   2 +-
 .../catalog/others/undertow-spring-security.json   |   2 +-
 .../org/apache/camel/catalog/others/zipkin.json    |   2 +-
 .../apache/camel/component/aws2/iam/aws2-iam.json  |   4 +-
 .../src/main/docs/aws2-iam-component.adoc          |   4 +-
 .../component/aws2/iam/IAM2Configuration.java      |   6 +-
 .../camel/component/aws2/iam/IAM2Producer.java     |   9 +-
 components/camel-aws2-sns/pom.xml                  |   4 +
 .../apache/camel/component/aws2/sns/aws2-sns.json  |   4 +-
 .../src/main/docs/aws2-sns-component.adoc          |   4 +-
 .../component/aws2/sns/Sns2Configuration.java      |   3 +-
 .../camel/component/aws2/sns/Sns2Endpoint.java     |  10 +-
 .../component/aws2/sns/AmazonSNSClientMock.java    |   1 -
 .../aws2/sns/SnsComponentConfigurationTest.java    |   6 +-
 .../camel/component/aws2/sns/SnsComponentTest.java |   2 +-
 .../org/apache/camel/component/aws2/sns/policy.txt |   1 +
 .../camel/component/aws2/sts/STS2Constants.java    |   2 +
 .../cxf/common/header/CxfHeaderHelper.java         |   6 +
 .../apache/camel/component/cxf/CXFTestSupport.java |   6 +
 .../jaxrs/CxfRsProducerHttpMethodHeaderTest.java   |  80 ++++++
 .../GoogleCalendarComponentConfigurer.java         |   6 +-
 .../calendar/GoogleCalendarEndpointConfigurer.java |   6 +-
 .../calendar/GoogleCalendarEndpointUriFactory.java |   7 +-
 .../GoogleCalendarStreamComponentConfigurer.java   |  15 ++
 .../GoogleCalendarStreamEndpointConfigurer.java    |  15 ++
 .../GoogleCalendarStreamEndpointUriFactory.java    |  10 +-
 .../component/google/calendar/google-calendar.json |  16 +-
 .../calendar/stream/google-calendar-stream.json    |  10 +-
 .../src/main/docs/google-calendar-component.adoc   |  12 +-
 .../docs/google-calendar-stream-component.adoc     |   5 +-
 .../calendar/GoogleCalendarConfiguration.java      |   8 +-
 .../stream/GoogleCalendarStreamComponent.java      |   7 +-
 .../stream/GoogleCalendarStreamConfiguration.java  |  43 +++-
 .../component/mail/MailComponentConfigurer.java    |   6 +
 .../component/mail/MailEndpointConfigurer.java     |   6 +
 .../component/mail/MailEndpointUriFactory.java     |   3 +-
 .../org/apache/camel/component/mail/imap.json      |   2 +
 .../org/apache/camel/component/mail/imaps.json     |   2 +
 .../org/apache/camel/component/mail/pop3.json      |   2 +
 .../org/apache/camel/component/mail/pop3s.json     |   2 +
 .../org/apache/camel/component/mail/smtp.json      |   2 +
 .../org/apache/camel/component/mail/smtps.json     |   2 +
 .../camel-mail/src/main/docs/mail-component.adoc   |   6 +-
 .../apache/camel/component/mail/MailBinding.java   |  13 +-
 .../camel/component/mail/MailConfiguration.java    |  14 ++
 .../apache/camel/component/mail/MailEndpoint.java  |   3 +-
 ... MailBindingAttachmentEncodedFilenameTest.java} |  38 +--
 .../SubscriptionHelperIntegrationTest.java         |  24 +-
 components/camel-servlet/pom.xml                   |   5 +
 ...st.java => RestJsonBindingInvalidDataTest.java} |  50 ++--
 .../src/main/docs/telegram-component.adoc          |   2 +-
 .../camel/impl/engine/AbstractCamelContext.java    |   3 +
 .../converter/CamelBaseBulkConverterLoader.java    |  10 +-
 .../org/apache/camel/converter/IOConverter.java    |  10 +-
 .../dsl/Aws2IamComponentBuilderFactory.java        |   4 +-
 .../dsl/Aws2SnsComponentBuilderFactory.java        |   4 +-
 .../dsl/GoogleCalendarComponentBuilderFactory.java |  98 ++++----
 ...oogleCalendarStreamComponentBuilderFactory.java |  49 ++++
 .../component/dsl/ImapComponentBuilderFactory.java |  18 ++
 .../dsl/ImapsComponentBuilderFactory.java          |  18 ++
 .../component/dsl/Pop3ComponentBuilderFactory.java |  18 ++
 .../dsl/Pop3sComponentBuilderFactory.java          |  18 ++
 .../component/dsl/SmtpComponentBuilderFactory.java |  18 ++
 .../dsl/SmtpsComponentBuilderFactory.java          |  18 ++
 .../dsl/GoogleCalendarEndpointBuilderFactory.java  | 270 ++++++++++-----------
 ...GoogleCalendarStreamEndpointBuilderFactory.java |  46 ++++
 .../endpoint/dsl/IAM2EndpointBuilderFactory.java   |  10 +-
 .../endpoint/dsl/MailEndpointBuilderFactory.java   |  36 +++
 .../endpoint/dsl/Sns2EndpointBuilderFactory.java   |   4 +-
 .../modules/ROOT/pages/aws2-iam-component.adoc     |   4 +-
 .../modules/ROOT/pages/aws2-sns-component.adoc     |   4 +-
 .../ROOT/pages/google-calendar-component.adoc      |  12 +-
 .../pages/google-calendar-stream-component.adoc    |   5 +-
 .../modules/ROOT/pages/mail-component.adoc         |   6 +-
 .../modules/ROOT/pages/telegram-component.adoc     |   2 +-
 .../ROOT/pages/camel-3x-upgrade-guide-3_8.adoc     |  12 +
 .../modules/ROOT/pages/camel-3x-upgrade-guide.adoc |   1 +
 parent/pom.xml                                     |  12 +-
 552 files changed, 1395 insertions(+), 842 deletions(-)
 create mode 100644 components/camel-aws2-sns/src/test/resources/org/apache/camel/component/aws2/sns/policy.txt
 create mode 100644 components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHttpMethodHeaderTest.java
 copy components/camel-mail/src/test/java/org/apache/camel/component/mail/{MailBindingAttachmentFileTest.java => MailBindingAttachmentEncodedFilenameTest.java} (63%)
 copy components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/{RestServletBindingModeAutoWithJsonTest.java => RestJsonBindingInvalidDataTest.java} (50%)
 create mode 100644 docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc


[camel] 01/03: CAMEL-12871: stub server and test

Posted by zr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

zregvart pushed a commit to branch issue/CAMEL-12871
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5f1e7e97d01f37509a74cffb5839642843610681
Author: Zoran Regvart <zr...@apache.org>
AuthorDate: Wed Dec 16 22:09:23 2020 +0100

    CAMEL-12871: stub server and test
    
    Adds a stub server implemented in Jetty, as it is already pulled in as a
    dependency, and a integration test for the testing streaming resiliency.
    
    Two cases are added in the integration test: server closing the
    TCP connection (e.g. in a abrupt server shutdown), and restarting the
    `SubscriptionHelper` service (e.g. when route is restarted).
---
 .../salesforce/internal/streaming/StubServer.java  | 295 ++++++++++++++++
 .../SubscriptionHelperIntegrationTest.java         | 372 +++++++++++++++++++++
 2 files changed, 667 insertions(+)

diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/StubServer.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/StubServer.java
new file mode 100644
index 0000000..76d5d1b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/StubServer.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.salesforce.internal.streaming;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.util.IOHelper;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.AbstractNetworkConnector;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class StubServer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(StubServer.class);
+
+    private final List<StubResponse> defaultStubs = new ArrayList<>();
+
+    private final Server server;
+
+    private final List<StubResponse> stubs = new ArrayList<>();
+
+    class StubHandler extends AbstractHandler {
+
+        @Override
+        public void handle(
+                final String target, final Request baseRequest, final HttpServletRequest request,
+                final HttpServletResponse response)
+                throws IOException, ServletException {
+            final String body;
+            try (Reader bodyReader = request.getReader()) {
+                body = IOHelper.toString(bodyReader);
+            }
+
+            final StubResponse stub = stubFor(request, body);
+
+            if (stub == null) {
+                LOG.error("Stub not found for {} {}", request.getMethod(), request.getRequestURI());
+                response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
+                return;
+            }
+
+            response.setStatus(stub.responseStatus);
+            response.setContentType("application/json;charset=UTF-8");
+
+            final String id = messageIdFrom(body);
+
+            try (Writer out = response.getWriter()) {
+                stub.writeTo(id, out);
+            }
+        }
+
+        private StubResponse stubFor(final HttpServletRequest request, final String body) throws IOException {
+            final List<StubResponse> allResponses = new ArrayList<>(defaultStubs);
+            allResponses.addAll(stubs);
+
+            for (final StubResponse stub : allResponses) {
+                if (stub.matches(request, body)) {
+                    return stub;
+                }
+            }
+
+            return null;
+        }
+
+    }
+
+    final class StubResponse {
+
+        private Predicate<String> requestCondition;
+
+        private final String requestMethod;
+
+        private final String requestPath;
+
+        private BlockingQueue<String> responseMessages;
+
+        private final int responseStatus;
+
+        private String responseString;
+
+        public StubResponse(final String requestMethod, final String requestPath, final int responseStatus,
+                            final Predicate<String> requestCondition,
+                            final BlockingQueue<String> responseMessages) {
+            this(requestMethod, requestPath, responseStatus, requestCondition);
+
+            this.responseMessages = responseMessages;
+        }
+
+        private StubResponse(final String requestMethod, final String requestPath, final int responseStatus) {
+            this.responseStatus = responseStatus;
+            this.requestMethod = Objects.requireNonNull(requestMethod, "requestMethod");
+            this.requestPath = Objects.requireNonNull(requestPath, "requestPath");
+        }
+
+        private StubResponse(final String requestMethod, final String requestPath, final int responseStatus,
+                             final BlockingQueue<String> responseMessages) {
+            this(requestMethod, requestPath, responseStatus);
+
+            this.responseMessages = responseMessages;
+        }
+
+        private StubResponse(final String requestMethod, final String requestPath, final int responseStatus,
+                             final Predicate<String> requestCondition) {
+            this(requestMethod, requestPath, responseStatus);
+
+            this.requestCondition = requestCondition;
+        }
+
+        private StubResponse(final String requestMethod, final String requestPath, final int responseStatus,
+                             final Predicate<String> requestCondition,
+                             final String responseString) {
+            this(requestMethod, requestPath, responseStatus, requestCondition);
+
+            this.responseString = responseString;
+        }
+
+        private StubResponse(final String requestMethod, final String requestPath, final int responseStatus,
+                             final String responseString) {
+            this(requestMethod, requestPath, responseStatus);
+            this.responseString = responseString;
+        }
+
+        @Override
+        public String toString() {
+            return requestMethod + " " + requestPath;
+        }
+
+        private boolean matches(final HttpServletRequest request, final String body) throws IOException {
+            final boolean matches = Objects.equals(requestMethod, request.getMethod())
+                    && Objects.equals(requestPath, request.getRequestURI());
+
+            if (!matches) {
+                return false;
+            }
+
+            if (requestCondition == null) {
+                return true;
+            }
+
+            return requestCondition.test(body);
+        }
+
+        private void writeTo(final String messageId, final Writer out) throws IOException {
+            if (responseString != null) {
+                out.write(responseString.replace("$id", messageId));
+                out.flush();
+                return;
+            }
+
+            if (responseMessages != null) {
+                while (true) {
+                    try {
+                        final String message = responseMessages.poll(25, TimeUnit.MILLISECONDS);
+                        if (message != null) {
+                            out.write(message.replace("$id", messageId));
+                            out.flush();
+                            return;
+                        }
+
+                        if (!server.isRunning()) {
+                            return;
+                        }
+                    } catch (final InterruptedException ignored) {
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    public StubServer() {
+        server = new Server(0);
+        server.setHandler(new StubHandler());
+
+        try {
+            server.start();
+        } catch (final Exception e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    @SuppressWarnings("resource")
+    public void abruptlyRestart() {
+        final int port = port();
+
+        stop();
+
+        connector().setPort(port);
+
+        try {
+            server.start();
+        } catch (final Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @SuppressWarnings("resource")
+    public int port() {
+        return connector().getLocalPort();
+    }
+
+    public void replyTo(final String method, final String path, final BlockingQueue<String> messages) {
+        stubs.add(new StubResponse(method, path, 200, messages));
+    }
+
+    public void replyTo(final String method, final String path, final int status) {
+        stubs.add(new StubResponse(method, path, status));
+    }
+
+    public void replyTo(
+            final String method, final String path, final Predicate<String> requestCondition,
+            final BlockingQueue<String> messages) {
+        stubs.add(new StubResponse(method, path, 200, requestCondition, messages));
+    }
+
+    public void replyTo(
+            final String method, final String path, final Predicate<String> requestCondition, final String response) {
+        stubs.add(new StubResponse(method, path, 200, requestCondition, response));
+    }
+
+    public void replyTo(final String method, final String path, final String response) {
+        stubs.add(new StubResponse(method, path, 200, response));
+    }
+
+    public void reset() {
+        stubs.clear();
+    }
+
+    public void stop() {
+        try {
+            for (final EndPoint endPoint : connector().getConnectedEndPoints()) {
+                endPoint.close();
+            }
+
+            server.stop();
+        } catch (final Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void stubsAsDefaults() {
+        defaultStubs.addAll(stubs);
+        stubs.clear();
+    }
+
+    private AbstractNetworkConnector connector() {
+        final AbstractNetworkConnector connector = (AbstractNetworkConnector) server.getConnectors()[0];
+        return connector;
+    }
+
+    private static String messageIdFrom(final String body) {
+        int idx = body.indexOf("\"id\":\"");
+        String id = "";
+
+        if (idx > 0) {
+            idx += 6;
+            char ch;
+            while (Character.isDigit(ch = body.charAt(idx++))) {
+                id += ch;
+            }
+        }
+        return id;
+    }
+
+}
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java
new file mode 100644
index 0000000..0491ca7
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.salesforce.internal.streaming;
+
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelException;
+import org.apache.camel.component.salesforce.AuthenticationType;
+import org.apache.camel.component.salesforce.SalesforceComponent;
+import org.apache.camel.component.salesforce.SalesforceConsumer;
+import org.apache.camel.component.salesforce.SalesforceEndpoint;
+import org.apache.camel.component.salesforce.SalesforceEndpointConfig;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.cometd.bayeux.Message;
+import org.cometd.bayeux.client.ClientSessionChannel;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mockito;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.camel.component.salesforce.internal.streaming.SubscriptionHelperIntegrationTest.MessageArgumentMatcher.messageForAccountCreationWithName;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@TestInstance(Lifecycle.PER_CLASS)
+public class SubscriptionHelperIntegrationTest {
+
+    final CamelContext camel;
+
+    final SalesforceEndpointConfig config = new SalesforceEndpointConfig();
+
+    final BlockingQueue<String> messages = new LinkedBlockingDeque<>();
+
+    final SalesforceComponent salesforce;
+
+    final StubServer server;
+
+    final SubscriptionHelper subscription;
+
+    SalesforceConsumer toUnsubscribe;
+
+    static class MessageArgumentMatcher implements ArgumentMatcher<Message> {
+
+        private final String name;
+
+        public MessageArgumentMatcher(final String name) {
+            this.name = name;
+        }
+
+        @Override
+        public boolean matches(final Message message) {
+            final Map<String, Object> data = message.getDataAsMap();
+
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> event = (Map<String, Object>) data.get("event");
+
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> sobject = (Map<String, Object>) data.get("sobject");
+
+            return "created".equals(event.get("type")) && name.equals(sobject.get("Name"));
+        }
+
+        static Message messageForAccountCreationWithName(final String name) {
+            return argThat(new MessageArgumentMatcher(name));
+        }
+
+    }
+
+    public SubscriptionHelperIntegrationTest() throws SalesforceException {
+        server = new StubServer();
+
+        LoggerFactory.getLogger(SubscriptionHelperIntegrationTest.class).info("Port for wireshark to filter: {}",
+                server.port());
+
+        final String instanceUrl = "http://localhost:" + server.port();
+
+        server.replyTo("POST", "/services/oauth2/token",
+                "{\"instance_url\":\"" + instanceUrl + "\",\"access_token\":\"token\"}");
+
+        server.replyTo("GET", "/services/oauth2/revoke?token=token", 200);
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/handshake", "[\n"
+                                                                                                     + "  {\n"
+                                                                                                     + "    \"ext\": {\n"
+                                                                                                     + "      \"replay\": true,\n"
+                                                                                                     + "      \"payload.format\": true\n"
+                                                                                                     + "    },\n"
+                                                                                                     + "    \"minimumVersion\": \"1.0\",\n"
+                                                                                                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                                                                                                     + "    \"supportedConnectionTypes\": [\n"
+                                                                                                     + "      \"long-polling\"\n"
+                                                                                                     + "    ],\n"
+                                                                                                     + "    \"channel\": \"/meta/handshake\",\n"
+                                                                                                     + "    \"id\": \"$id\",\n"
+                                                                                                     + "    \"version\": \"1.0\",\n"
+                                                                                                     + "    \"successful\": true\n"
+                                                                                                     + "  }\n"
+                                                                                                     + "]");
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/connect",
+                req -> req.contains("\"timeout\":0"), "[\n"
+                                                        + "  {\n"
+                                                        + "    \"clientId\": \"1f0agp5a95yiaeb1kifib37r5z4g\",\n"
+                                                        + "    \"advice\": {\n"
+                                                        + "      \"interval\": 0,\n"
+                                                        + "      \"timeout\": 110000,\n"
+                                                        + "      \"reconnect\": \"retry\"\n"
+                                                        + "    },\n"
+                                                        + "    \"channel\": \"/meta/connect\",\n"
+                                                        + "    \"id\": \"$id\",\n"
+                                                        + "    \"successful\": true\n"
+                                                        + "  }\n"
+                                                        + "]");
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/connect", messages);
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/subscribe", "[\n"
+                                                                                                     + "  {\n"
+                                                                                                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                                                                                                     + "    \"channel\": \"/meta/subscribe\",\n"
+                                                                                                     + "    \"id\": \"$id\",\n"
+                                                                                                     + "    \"subscription\": \"/topic/Account\",\n"
+                                                                                                     + "    \"successful\": true\n"
+                                                                                                     + "  }\n"
+                                                                                                     + "]");
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/unsubscribe", "[\n"
+                                                                                                       + "  {\n"
+                                                                                                       + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                                                                                                       + "    \"channel\": \"/meta/unsubscribe\",\n"
+                                                                                                       + "    \"id\": \"$id\",\n"
+                                                                                                       + "    \"subscription\": \"/topic/Account\",\n"
+                                                                                                       + "    \"successful\": true\n"
+                                                                                                       + "  }\n"
+                                                                                                       + "]");
+
+        server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/disconnect", "[\n"
+                                                                                                      + "  {\n"
+                                                                                                      + "     \"channel\": \"/meta/disconnect\",\n"
+                                                                                                      + "     \"clientId\": \"client-id\"\n"
+                                                                                                      + "   }\n"
+                                                                                                      + "]");
+
+        server.replyTo("GET", "/services/oauth2/revoke", 200);
+
+        server.stubsAsDefaults();
+
+        camel = new DefaultCamelContext();
+        camel.start();
+        salesforce = new SalesforceComponent(camel);
+        salesforce.setLoginUrl(instanceUrl);
+        salesforce.setClientId("clientId");
+        salesforce.setClientSecret("clientSecret");
+        salesforce.setRefreshToken("refreshToken");
+        salesforce.setAuthenticationType(AuthenticationType.REFRESH_TOKEN);
+        salesforce.setConfig(config);
+
+        salesforce.start();
+        subscription = new SubscriptionHelper(salesforce);
+    }
+
+    @BeforeEach
+    public void cleanSlate() throws CamelException {
+        if (toUnsubscribe != null) {
+            subscription.unsubscribe("Account", toUnsubscribe);
+        }
+        server.reset();
+    }
+
+    @AfterAll
+    public void stop() {
+        salesforce.stop();
+        camel.stop();
+        server.stop();
+    }
+
+    @Test
+    void shouldResubscribeOnConnectionFailures() throws InterruptedException {
+        // handshake and connect
+        subscription.start();
+
+        final SalesforceConsumer consumer
+                = toUnsubscribe = mock(SalesforceConsumer.class, "shouldResubscribeOnConnectionFailures:consumer");
+
+        final SalesforceEndpoint endpoint = mock(SalesforceEndpoint.class, "shouldResubscribeOnConnectionFailures:endpoint");
+
+        // subscribe
+        when(consumer.getTopicName()).thenReturn("Account");
+
+        when(consumer.getEndpoint()).thenReturn(endpoint);
+        when(endpoint.getConfiguration()).thenReturn(config);
+        when(endpoint.getComponent()).thenReturn(salesforce);
+        when(endpoint.getTopicName()).thenReturn("Account");
+
+        subscription.subscribe("Account", consumer);
+
+        // push one message so we know connection is established and consumer
+        // receives notifications
+        messages.add("[\n"
+                     + "  {\n"
+                     + "    \"data\": {\n"
+                     + "      \"event\": {\n"
+                     + "        \"createdDate\": \"2020-12-11T13:44:56.891Z\",\n"
+                     + "        \"replayId\": 1,\n"
+                     + "        \"type\": \"created\"\n"
+                     + "      },\n"
+                     + "      \"sobject\": {\n"
+                     + "        \"Id\": \"0011n00002XWMgVAAX\",\n"
+                     + "        \"Name\": \"shouldResubscribeOnConnectionFailures 1\"\n"
+                     + "      }\n"
+                     + "    },\n"
+                     + "    \"channel\": \"/topic/Account\"\n"
+                     + "  },\n"
+                     + "  {\n"
+                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                     + "    \"channel\": \"/meta/connect\",\n"
+                     + "    \"id\": \"$id\",\n"
+                     + "    \"successful\": true\n"
+                     + "  }\n"
+                     + "]");
+
+        verify(consumer, Mockito.timeout(100)).processMessage(any(ClientSessionChannel.class),
+                messageForAccountCreationWithName("shouldResubscribeOnConnectionFailures 1"));
+
+        // terminate server abruptly by closing the connection (sends FIN, ACK)
+        server.abruptlyRestart();
+
+        // queue next message for when the client recovers
+        messages.add("[\n"
+                     + "  {\n"
+                     + "    \"data\": {\n"
+                     + "      \"event\": {\n"
+                     + "        \"createdDate\": \"2020-12-11T13:44:56.891Z\",\n"
+                     + "        \"replayId\": 2,\n"
+                     + "        \"type\": \"created\"\n"
+                     + "      },\n"
+                     + "      \"sobject\": {\n"
+                     + "        \"Id\": \"0011n00002XWMgVAAX\",\n"
+                     + "        \"Name\": \"shouldResubscribeOnConnectionFailures 2\"\n"
+                     + "      }\n"
+                     + "    },\n"
+                     + "    \"channel\": \"/topic/Account\"\n"
+                     + "  },\n"
+                     + "  {\n"
+                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                     + "    \"channel\": \"/meta/connect\",\n"
+                     + "    \"id\": \"$id\",\n"
+                     + "    \"successful\": true\n"
+                     + "  }\n"
+                     + "]");
+
+        // assert last message was received, recovery can take a bit
+        verify(consumer, timeout(10000)).processMessage(any(ClientSessionChannel.class),
+                messageForAccountCreationWithName("shouldResubscribeOnConnectionFailures 2"));
+
+        verify(consumer, atLeastOnce()).getEndpoint();
+        verify(consumer, atLeastOnce()).getTopicName();
+        verifyNoMoreInteractions(consumer);
+    }
+
+    @Test
+    void shouldResubscribeOnHelperRestart() {
+        // handshake and connect
+        subscription.start();
+
+        final SalesforceConsumer consumer
+                = toUnsubscribe = mock(SalesforceConsumer.class, "shouldResubscribeOnHelperRestart:consumer");
+
+        final SalesforceEndpoint endpoint = mock(SalesforceEndpoint.class, "shouldResubscribeOnHelperRestart:endpoint");
+
+        // subscribe
+        when(consumer.getTopicName()).thenReturn("Account");
+
+        when(consumer.getEndpoint()).thenReturn(endpoint);
+        when(endpoint.getConfiguration()).thenReturn(config);
+        when(endpoint.getComponent()).thenReturn(salesforce);
+        when(endpoint.getTopicName()).thenReturn("Account");
+
+        subscription.subscribe("Account", consumer);
+
+        // push one message so we know connection is established and consumer
+        // receives notifications
+        messages.add("[\n"
+                     + "  {\n"
+                     + "    \"data\": {\n"
+                     + "      \"event\": {\n"
+                     + "        \"createdDate\": \"2020-12-11T13:44:56.891Z\",\n"
+                     + "        \"replayId\": 1,\n"
+                     + "        \"type\": \"created\"\n"
+                     + "      },\n"
+                     + "      \"sobject\": {\n"
+                     + "        \"Id\": \"0011n00002XWMgVAAX\",\n"
+                     + "        \"Name\": \"shouldResubscribeOnHelperRestart 1\"\n"
+                     + "      }\n"
+                     + "    },\n"
+                     + "    \"channel\": \"/topic/Account\"\n"
+                     + "  },\n"
+                     + "  {\n"
+                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                     + "    \"channel\": \"/meta/connect\",\n"
+                     + "    \"id\": \"$id\",\n"
+                     + "    \"successful\": true\n"
+                     + "  }\n"
+                     + "]");
+        verify(consumer, timeout(100)).processMessage(any(ClientSessionChannel.class),
+                messageForAccountCreationWithName("shouldResubscribeOnHelperRestart 1"));
+
+        // stop and start the subscription helper
+        subscription.stop();
+        subscription.start();
+
+        // queue next message for when the client recovers
+        messages.add("[\n"
+                     + "  {\n"
+                     + "    \"data\": {\n"
+                     + "      \"event\": {\n"
+                     + "        \"createdDate\": \"2020-12-11T13:44:56.891Z\",\n"
+                     + "        \"replayId\": 2,\n"
+                     + "        \"type\": \"created\"\n"
+                     + "      },\n"
+                     + "      \"sobject\": {\n"
+                     + "        \"Id\": \"0011n00002XWMgVAAX\",\n"
+                     + "        \"Name\": \"shouldResubscribeOnHelperRestart 2\"\n"
+                     + "      }\n"
+                     + "    },\n"
+                     + "    \"channel\": \"/topic/Account\"\n"
+                     + "  },\n"
+                     + "  {\n"
+                     + "    \"clientId\": \"5ra4927ikfky6cb12juthkpofeu8\",\n"
+                     + "    \"channel\": \"/meta/connect\",\n"
+                     + "    \"id\": \"$id\",\n"
+                     + "    \"successful\": true\n"
+                     + "  }\n"
+                     + "]");
+
+        // assert last message was received, recovery can take a bit
+        verify(consumer, timeout(2000)).processMessage(any(ClientSessionChannel.class),
+                messageForAccountCreationWithName("shouldResubscribeOnHelperRestart 2"));
+
+        verify(consumer, atLeastOnce()).getEndpoint();
+        verify(consumer, atLeastOnce()).getTopicName();
+        verifyNoMoreInteractions(consumer);
+    }
+}


[camel] 02/03: CAMEL-12871: release resources on stop

Posted by zr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

zregvart pushed a commit to branch issue/CAMEL-12871
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 2fada1099e6afba4a6bee81000b0f9c3104ef6e3
Author: Zoran Regvart <zr...@apache.org>
AuthorDate: Wed Dec 16 14:41:17 2020 +0100

    CAMEL-12871: release resources on stop
    
    When SubscriptionHelper is stopped we need to remove all listeners and
    close channels this helper is listening on.
---
 .../internal/streaming/SubscriptionHelper.java     | 29 +++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
index 625b2f2..25e363b 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
@@ -36,6 +36,7 @@ import org.apache.camel.component.salesforce.internal.SalesforceSession;
 import org.apache.camel.support.service.ServiceSupport;
 import org.cometd.bayeux.Message;
 import org.cometd.bayeux.client.ClientSessionChannel;
+import org.cometd.bayeux.client.ClientSessionChannel.MessageListener;
 import org.cometd.client.BayeuxClient;
 import org.cometd.client.BayeuxClient.State;
 import org.cometd.client.transport.ClientTransport;
@@ -320,11 +321,33 @@ public class SubscriptionHelper extends ServiceSupport {
         return exception;
     }
 
+    private void closeChannel(final String name, MessageListener listener) {
+        if (client == null) {
+            return;
+        }
+
+        final ClientSessionChannel channel = client.getChannel(name);
+        channel.removeListener(listener);
+        channel.release();
+    }
+
     @Override
     protected void doStop() throws Exception {
-        client.getChannel(META_DISCONNECT).removeListener(disconnectListener);
-        client.getChannel(META_CONNECT).removeListener(connectListener);
-        client.getChannel(META_HANDSHAKE).removeListener(handshakeListener);
+        closeChannel(META_DISCONNECT, disconnectListener);
+        closeChannel(META_CONNECT, connectListener);
+        closeChannel(META_HANDSHAKE, handshakeListener);
+
+        for (Map.Entry<SalesforceConsumer, MessageListener> entry : listenerMap.entrySet()) {
+            final SalesforceConsumer consumer = entry.getKey();
+            final String topic = consumer.getTopicName();
+
+            final MessageListener listener = entry.getValue();
+            closeChannel(getChannelName(topic), listener);
+        }
+
+        if (client == null) {
+            return;
+        }
 
         client.disconnect();
         boolean disconnected = client.waitFor(timeout, State.DISCONNECTED);


[camel] 03/03: CAMEL-12871: disconnect on handshake failure

Posted by zr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

zregvart pushed a commit to branch issue/CAMEL-12871
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e1760b1de6adbb5a0f10c02c677e69a04feaad26
Author: Zoran Regvart <zr...@apache.org>
AuthorDate: Wed Dec 16 14:43:13 2020 +0100

    CAMEL-12871: disconnect on handshake failure
    
    If we can't connect and perform the handshake, disconnecting will
    trigger client restart with back-off. Also when restarting as the signal
    to restart can occur on multiple threads we need to guard against
    restart happening in parallel.
---
 .../internal/streaming/SubscriptionHelper.java     | 132 ++++++++++++---------
 .../SubscriptionHelperIntegrationTest.java         |  24 ++--
 2 files changed, 89 insertions(+), 67 deletions(-)

diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
index 25e363b..c97fb02 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelper.java
@@ -22,6 +22,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Stream;
 
@@ -93,6 +94,7 @@ public class SubscriptionHelper extends ServiceSupport {
 
     private volatile boolean reconnecting;
     private final AtomicLong restartBackoff;
+    private final AtomicBoolean restarting = new AtomicBoolean();
 
     public SubscriptionHelper(final SalesforceComponent component) throws SalesforceException {
         this.component = component;
@@ -173,6 +175,7 @@ public class SubscriptionHelper extends ServiceSupport {
                         connectError = (String) message.get(ERROR_FIELD);
                         connectException = getFailure(message);
 
+                        client.disconnect();
                     } else if (reconnecting) {
 
                         reconnecting = false;
@@ -206,6 +209,10 @@ public class SubscriptionHelper extends ServiceSupport {
         }
         client.getChannel(META_DISCONNECT).addListener(disconnectListener);
 
+        connect();
+    }
+
+    private void connect() throws CamelException {
         // connect to Salesforce cometd endpoint
         client.handshake();
 
@@ -229,80 +236,95 @@ public class SubscriptionHelper extends ServiceSupport {
 
     // launch an async task to restart
     private void restartClient() {
+        if (!restarting.compareAndSet(false, true)) {
+            return;
+        }
 
         // launch a new restart command
         final SalesforceHttpClient httpClient = component.getConfig().getHttpClient();
         httpClient.getExecutor().execute(new Runnable() {
             @Override
             public void run() {
+                try {
+                    performClientRestart();
+                } finally {
+                    restarting.set(false);
+                }
+            }
+        });
+    }
 
-                LOG.info("Restarting on unexpected disconnect from Salesforce...");
-                boolean abort = false;
+    private void performClientRestart() {
+        if (isStoppingOrStopped()) {
+            return;
+        }
 
-                // wait for disconnect
-                LOG.debug("Waiting to disconnect...");
-                while (!client.isDisconnected()) {
-                    try {
-                        Thread.sleep(DISCONNECT_INTERVAL);
-                    } catch (InterruptedException e) {
-                        LOG.error("Aborting restart on interrupt!");
-                        abort = true;
-                    }
-                }
+        LOG.info("Restarting on unexpected disconnect from Salesforce...");
+        boolean abort = false;
+
+        // wait for disconnect
+        LOG.debug("Waiting to disconnect...");
+        while (!abort && !client.isDisconnected()) {
+            try {
+                Thread.sleep(DISCONNECT_INTERVAL);
+            } catch (InterruptedException e) {
+                LOG.error("Aborting restart on interrupt!");
+                abort = true;
+            }
 
-                if (!abort) {
+            abort = isStoppingOrStopped();
+        }
 
-                    // update restart attempt backoff
-                    final long backoff = restartBackoff.getAndAdd(backoffIncrement);
-                    if (backoff > maxBackoff) {
-                        LOG.error("Restart aborted after exceeding {} msecs backoff", maxBackoff);
-                        abort = true;
-                    } else {
+        if (!abort) {
 
-                        // pause before restart attempt
-                        LOG.debug("Pausing for {} msecs before restart attempt", backoff);
-                        try {
-                            Thread.sleep(backoff);
-                        } catch (InterruptedException e) {
-                            LOG.error("Aborting restart on interrupt!");
-                            abort = true;
-                        }
-                    }
+            // update restart attempt backoff
+            final long backoff = restartBackoff.getAndAdd(backoffIncrement);
+            if (backoff > maxBackoff) {
+                LOG.error("Restart aborted after exceeding {} msecs backoff", maxBackoff);
+                abort = true;
+            } else {
 
-                    if (!abort) {
-                        Exception lastError = new SalesforceException("Unknown error", null);
-                        try {
-                            // reset client
-                            doStop();
+                // pause before restart attempt
+                LOG.debug("Pausing for {} msecs before restart attempt", backoff);
+                try {
+                    Thread.sleep(backoff);
+                } catch (InterruptedException e) {
+                    LOG.error("Aborting restart on interrupt!");
+                    abort = true;
+                }
+            }
 
-                            // register listeners and restart
-                            doStart();
+            if (!abort) {
+                Exception lastError = new SalesforceException("Unknown error", null);
+                try {
+                    // reset client
+                    doStop();
 
-                        } catch (Exception e) {
-                            LOG.error("Error restarting: " + e.getMessage(), e);
-                            lastError = e;
-                        }
+                    // register listeners and restart
+                    doStart();
 
-                        if (client != null && client.isHandshook()) {
-                            LOG.info("Successfully restarted!");
-                            // reset backoff interval
-                            restartBackoff.set(client.getBackoffIncrement());
-                        } else {
-                            LOG.error("Failed to restart after pausing for {} msecs", backoff);
-                            if ((backoff + backoffIncrement) > maxBackoff) {
-                                // notify all consumers
-                                String abortMsg = "Aborting restart attempt due to: " + lastError.getMessage();
-                                SalesforceException ex = new SalesforceException(abortMsg, lastError);
-                                for (SalesforceConsumer consumer : listenerMap.keySet()) {
-                                    consumer.handleException(abortMsg, ex);
-                                }
-                            }
+                } catch (Exception e) {
+                    LOG.error("Error restarting: " + e.getMessage(), e);
+                    lastError = e;
+                }
+
+                if (client != null && client.isHandshook()) {
+                    LOG.info("Successfully restarted!");
+                    // reset backoff interval
+                    restartBackoff.set(client.getBackoffIncrement());
+                } else {
+                    LOG.error("Failed to restart after pausing for {} msecs", backoff);
+                    if ((backoff + backoffIncrement) > maxBackoff) {
+                        // notify all consumers
+                        String abortMsg = "Aborting restart attempt due to: " + lastError.getMessage();
+                        SalesforceException ex = new SalesforceException(abortMsg, lastError);
+                        for (SalesforceConsumer consumer : listenerMap.keySet()) {
+                            consumer.handleException(abortMsg, ex);
                         }
                     }
                 }
-
             }
-        });
+        }
     }
 
     @SuppressWarnings("unchecked")
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java
index 0491ca7..8c01631 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/streaming/SubscriptionHelperIntegrationTest.java
@@ -127,18 +127,18 @@ public class SubscriptionHelperIntegrationTest {
 
         server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/connect",
                 req -> req.contains("\"timeout\":0"), "[\n"
-                                                        + "  {\n"
-                                                        + "    \"clientId\": \"1f0agp5a95yiaeb1kifib37r5z4g\",\n"
-                                                        + "    \"advice\": {\n"
-                                                        + "      \"interval\": 0,\n"
-                                                        + "      \"timeout\": 110000,\n"
-                                                        + "      \"reconnect\": \"retry\"\n"
-                                                        + "    },\n"
-                                                        + "    \"channel\": \"/meta/connect\",\n"
-                                                        + "    \"id\": \"$id\",\n"
-                                                        + "    \"successful\": true\n"
-                                                        + "  }\n"
-                                                        + "]");
+                                                      + "  {\n"
+                                                      + "    \"clientId\": \"1f0agp5a95yiaeb1kifib37r5z4g\",\n"
+                                                      + "    \"advice\": {\n"
+                                                      + "      \"interval\": 0,\n"
+                                                      + "      \"timeout\": 110000,\n"
+                                                      + "      \"reconnect\": \"retry\"\n"
+                                                      + "    },\n"
+                                                      + "    \"channel\": \"/meta/connect\",\n"
+                                                      + "    \"id\": \"$id\",\n"
+                                                      + "    \"successful\": true\n"
+                                                      + "  }\n"
+                                                      + "]");
 
         server.replyTo("POST", "/cometd/" + SalesforceEndpointConfig.DEFAULT_VERSION + "/connect", messages);