Search in sources :

Example 71 with ConnectException

use of org.apache.kafka.connect.errors.ConnectException in project kafka by apache.

the class TopicAdmin method endOffsets.

/**
 * Fetch the most recent offset for each of the supplied {@link TopicPartition} objects.
 *
 * @param partitions the topic partitions
 * @return the map of offset for each topic partition, or an empty map if the supplied partitions
 *         are null or empty
 * @throws UnsupportedVersionException if the admin client cannot read end offsets
 * @throws TimeoutException if the offset metadata could not be fetched before the amount of time allocated
 *         by {@code request.timeout.ms} expires, and this call can be retried
 * @throws LeaderNotAvailableException if the leader was not available and this call can be retried
 * @throws RetriableException if a retriable error occurs, or the thread is interrupted while attempting
 *         to perform this operation
 * @throws ConnectException if a non retriable error occurs
 */
public Map<TopicPartition, Long> endOffsets(Set<TopicPartition> partitions) {
    if (partitions == null || partitions.isEmpty()) {
        return Collections.emptyMap();
    }
    Map<TopicPartition, OffsetSpec> offsetSpecMap = partitions.stream().collect(Collectors.toMap(Function.identity(), tp -> OffsetSpec.latest()));
    ListOffsetsResult resultFuture = admin.listOffsets(offsetSpecMap);
    // Get the individual result for each topic partition so we have better error messages
    Map<TopicPartition, Long> result = new HashMap<>();
    for (TopicPartition partition : partitions) {
        try {
            ListOffsetsResultInfo info = resultFuture.partitionResult(partition).get();
            result.put(partition, info.offset());
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();
            String topic = partition.topic();
            if (cause instanceof AuthorizationException) {
                String msg = String.format("Not authorized to get the end offsets for topic '%s' on brokers at %s", topic, bootstrapServers());
                throw new ConnectException(msg, e);
            } else if (cause instanceof UnsupportedVersionException) {
                // Should theoretically never happen, because this method is the same as what the consumer uses and therefore
                // should exist in the broker since before the admin client was added
                String msg = String.format("API to get the get the end offsets for topic '%s' is unsupported on brokers at %s", topic, bootstrapServers());
                throw new UnsupportedVersionException(msg, e);
            } else if (cause instanceof TimeoutException) {
                String msg = String.format("Timed out while waiting to get end offsets for topic '%s' on brokers at %s", topic, bootstrapServers());
                throw new TimeoutException(msg, e);
            } else if (cause instanceof LeaderNotAvailableException) {
                String msg = String.format("Unable to get end offsets during leader election for topic '%s' on brokers at %s", topic, bootstrapServers());
                throw new LeaderNotAvailableException(msg, e);
            } else if (cause instanceof org.apache.kafka.common.errors.RetriableException) {
                throw (org.apache.kafka.common.errors.RetriableException) cause;
            } else {
                String msg = String.format("Error while getting end offsets for topic '%s' on brokers at %s", topic, bootstrapServers());
                throw new ConnectException(msg, e);
            }
        } catch (InterruptedException e) {
            Thread.interrupted();
            String msg = String.format("Interrupted while attempting to read end offsets for topic '%s' on brokers at %s", partition.topic(), bootstrapServers());
            throw new RetriableException(msg, e);
        }
    }
    return result;
}
Also used : Config(org.apache.kafka.clients.admin.Config) Arrays(java.util.Arrays) DescribeTopicsOptions(org.apache.kafka.clients.admin.DescribeTopicsOptions) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) ConfigEntry(org.apache.kafka.clients.admin.ConfigEntry) ClusterAuthorizationException(org.apache.kafka.common.errors.ClusterAuthorizationException) LeaderNotAvailableException(org.apache.kafka.common.errors.LeaderNotAvailableException) Function(java.util.function.Function) HashSet(java.util.HashSet) ListOffsetsResult(org.apache.kafka.clients.admin.ListOffsetsResult) ConfigResource(org.apache.kafka.common.config.ConfigResource) Duration(java.time.Duration) Map(java.util.Map) Admin(org.apache.kafka.clients.admin.Admin) TopicDescription(org.apache.kafka.clients.admin.TopicDescription) TopicConfig(org.apache.kafka.common.config.TopicConfig) Utils(org.apache.kafka.common.utils.Utils) TopicPartition(org.apache.kafka.common.TopicPartition) InvalidConfigurationException(org.apache.kafka.common.errors.InvalidConfigurationException) TimeoutException(org.apache.kafka.common.errors.TimeoutException) Logger(org.slf4j.Logger) DescribeConfigsOptions(org.apache.kafka.clients.admin.DescribeConfigsOptions) AuthorizationException(org.apache.kafka.common.errors.AuthorizationException) AdminClientConfig(org.apache.kafka.clients.admin.AdminClientConfig) Collection(java.util.Collection) NewTopic(org.apache.kafka.clients.admin.NewTopic) Set(java.util.Set) KafkaFuture(org.apache.kafka.common.KafkaFuture) ConfigException(org.apache.kafka.common.config.ConfigException) Collectors(java.util.stream.Collectors) OffsetSpec(org.apache.kafka.clients.admin.OffsetSpec) Objects(java.util.Objects) ExecutionException(java.util.concurrent.ExecutionException) ListOffsetsResultInfo(org.apache.kafka.clients.admin.ListOffsetsResult.ListOffsetsResultInfo) RetriableException(org.apache.kafka.connect.errors.RetriableException) TopicExistsException(org.apache.kafka.common.errors.TopicExistsException) ConnectException(org.apache.kafka.connect.errors.ConnectException) TopicAuthorizationException(org.apache.kafka.common.errors.TopicAuthorizationException) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException) Optional(java.util.Optional) UnknownTopicOrPartitionException(org.apache.kafka.common.errors.UnknownTopicOrPartitionException) CreateTopicsOptions(org.apache.kafka.clients.admin.CreateTopicsOptions) Collections(java.util.Collections) ListOffsetsResultInfo(org.apache.kafka.clients.admin.ListOffsetsResult.ListOffsetsResultInfo) HashMap(java.util.HashMap) ClusterAuthorizationException(org.apache.kafka.common.errors.ClusterAuthorizationException) AuthorizationException(org.apache.kafka.common.errors.AuthorizationException) TopicAuthorizationException(org.apache.kafka.common.errors.TopicAuthorizationException) LeaderNotAvailableException(org.apache.kafka.common.errors.LeaderNotAvailableException) ListOffsetsResult(org.apache.kafka.clients.admin.ListOffsetsResult) TopicPartition(org.apache.kafka.common.TopicPartition) OffsetSpec(org.apache.kafka.clients.admin.OffsetSpec) ExecutionException(java.util.concurrent.ExecutionException) ConnectException(org.apache.kafka.connect.errors.ConnectException) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException) TimeoutException(org.apache.kafka.common.errors.TimeoutException) RetriableException(org.apache.kafka.connect.errors.RetriableException)

Example 72 with ConnectException

use of org.apache.kafka.connect.errors.ConnectException in project kafka by apache.

the class TopicAdmin method createOrFindTopics.

/**
 * Attempt to create the topics described by the given definitions, returning all of the names of those topics that
 * were created by this request. Any existing topics with the same name are unchanged, and the names of such topics
 * are excluded from the result.
 * <p>
 * If multiple topic definitions have the same topic name, the last one with that name will be used.
 * <p>
 * Apache Kafka added support for creating topics in 0.10.1.0, so this method works as expected with that and later versions.
 * With brokers older than 0.10.1.0, this method is unable to create topics and always returns an empty set.
 *
 * @param topics the specifications of the topics
 * @return the {@link TopicCreationResponse} with the names of the newly created and existing topics;
 *         never null but possibly empty
 * @throws ConnectException if an error occurs, the operation takes too long, or the thread is interrupted while
 *                          attempting to perform this operation
 */
public TopicCreationResponse createOrFindTopics(NewTopic... topics) {
    Map<String, NewTopic> topicsByName = new HashMap<>();
    if (topics != null) {
        for (NewTopic topic : topics) {
            if (topic != null)
                topicsByName.put(topic.name(), topic);
        }
    }
    if (topicsByName.isEmpty())
        return EMPTY_CREATION;
    String bootstrapServers = bootstrapServers();
    String topicNameList = Utils.join(topicsByName.keySet(), "', '");
    // Attempt to create any missing topics
    CreateTopicsOptions args = new CreateTopicsOptions().validateOnly(false);
    Map<String, KafkaFuture<Void>> newResults = admin.createTopics(topicsByName.values(), args).values();
    // Iterate over each future so that we can handle individual failures like when some topics already exist
    Set<String> newlyCreatedTopicNames = new HashSet<>();
    Set<String> existingTopicNames = new HashSet<>();
    for (Map.Entry<String, KafkaFuture<Void>> entry : newResults.entrySet()) {
        String topic = entry.getKey();
        try {
            entry.getValue().get();
            if (logCreation) {
                log.info("Created topic {} on brokers at {}", topicsByName.get(topic), bootstrapServers);
            }
            newlyCreatedTopicNames.add(topic);
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();
            if (cause instanceof TopicExistsException) {
                log.debug("Found existing topic '{}' on the brokers at {}", topic, bootstrapServers);
                existingTopicNames.add(topic);
                continue;
            }
            if (cause instanceof UnsupportedVersionException) {
                log.debug("Unable to create topic(s) '{}' since the brokers at {} do not support the CreateTopics API." + " Falling back to assume topic(s) exist or will be auto-created by the broker.", topicNameList, bootstrapServers);
                return EMPTY_CREATION;
            }
            if (cause instanceof ClusterAuthorizationException) {
                log.debug("Not authorized to create topic(s) '{}' upon the brokers {}." + " Falling back to assume topic(s) exist or will be auto-created by the broker.", topicNameList, bootstrapServers);
                return EMPTY_CREATION;
            }
            if (cause instanceof TopicAuthorizationException) {
                log.debug("Not authorized to create topic(s) '{}' upon the brokers {}." + " Falling back to assume topic(s) exist or will be auto-created by the broker.", topicNameList, bootstrapServers);
                return EMPTY_CREATION;
            }
            if (cause instanceof InvalidConfigurationException) {
                throw new ConnectException("Unable to create topic(s) '" + topicNameList + "': " + cause.getMessage(), cause);
            }
            if (cause instanceof TimeoutException) {
                // Timed out waiting for the operation to complete
                throw new ConnectException("Timed out while checking for or creating topic(s) '" + topicNameList + "'." + " This could indicate a connectivity issue, unavailable topic partitions, or if" + " this is your first use of the topic it may have taken too long to create.", cause);
            }
            throw new ConnectException("Error while attempting to create/find topic(s) '" + topicNameList + "'", e);
        } catch (InterruptedException e) {
            Thread.interrupted();
            throw new ConnectException("Interrupted while attempting to create/find topic(s) '" + topicNameList + "'", e);
        }
    }
    return new TopicCreationResponse(newlyCreatedTopicNames, existingTopicNames);
}
Also used : KafkaFuture(org.apache.kafka.common.KafkaFuture) HashMap(java.util.HashMap) CreateTopicsOptions(org.apache.kafka.clients.admin.CreateTopicsOptions) TopicExistsException(org.apache.kafka.common.errors.TopicExistsException) InvalidConfigurationException(org.apache.kafka.common.errors.InvalidConfigurationException) NewTopic(org.apache.kafka.clients.admin.NewTopic) ExecutionException(java.util.concurrent.ExecutionException) HashMap(java.util.HashMap) Map(java.util.Map) ClusterAuthorizationException(org.apache.kafka.common.errors.ClusterAuthorizationException) TopicAuthorizationException(org.apache.kafka.common.errors.TopicAuthorizationException) HashSet(java.util.HashSet) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException) ConnectException(org.apache.kafka.connect.errors.ConnectException) TimeoutException(org.apache.kafka.common.errors.TimeoutException)

Example 73 with ConnectException

use of org.apache.kafka.connect.errors.ConnectException in project kafka by apache.

the class TopicAdmin method describeTopics.

/**
 * Attempt to fetch the descriptions of the given topics
 * Apache Kafka added support for describing topics in 0.10.0.0, so this method works as expected with that and later versions.
 * With brokers older than 0.10.0.0, this method is unable to describe topics and always returns an empty set.
 *
 * @param topics the topics to describe
 * @return a map of topic names to topic descriptions of the topics that were requested; never null but possibly empty
 * @throws RetriableException if a retriable error occurs, the operation takes too long, or the
 * thread is interrupted while attempting to perform this operation
 * @throws ConnectException if a non retriable error occurs
 */
public Map<String, TopicDescription> describeTopics(String... topics) {
    if (topics == null) {
        return Collections.emptyMap();
    }
    String bootstrapServers = bootstrapServers();
    String topicNameList = String.join(", ", topics);
    Map<String, KafkaFuture<TopicDescription>> newResults = admin.describeTopics(Arrays.asList(topics), new DescribeTopicsOptions()).topicNameValues();
    // Iterate over each future so that we can handle individual failures like when some topics don't exist
    Map<String, TopicDescription> existingTopics = new HashMap<>();
    newResults.forEach((topic, desc) -> {
        try {
            existingTopics.put(topic, desc.get());
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();
            if (cause instanceof UnknownTopicOrPartitionException) {
                log.debug("Topic '{}' does not exist on the brokers at {}", topic, bootstrapServers);
                return;
            }
            if (cause instanceof ClusterAuthorizationException || cause instanceof TopicAuthorizationException) {
                String msg = String.format("Not authorized to describe topic(s) '%s' on the brokers %s", topicNameList, bootstrapServers);
                throw new ConnectException(msg, cause);
            }
            if (cause instanceof UnsupportedVersionException) {
                String msg = String.format("Unable to describe topic(s) '%s' since the brokers " + "at %s do not support the DescribeTopics API.", topicNameList, bootstrapServers);
                throw new ConnectException(msg, cause);
            }
            if (cause instanceof TimeoutException) {
                // Timed out waiting for the operation to complete
                throw new RetriableException("Timed out while describing topics '" + topicNameList + "'", cause);
            }
            throw new ConnectException("Error while attempting to describe topics '" + topicNameList + "'", e);
        } catch (InterruptedException e) {
            Thread.interrupted();
            throw new RetriableException("Interrupted while attempting to describe topics '" + topicNameList + "'", e);
        }
    });
    return existingTopics;
}
Also used : KafkaFuture(org.apache.kafka.common.KafkaFuture) HashMap(java.util.HashMap) UnknownTopicOrPartitionException(org.apache.kafka.common.errors.UnknownTopicOrPartitionException) DescribeTopicsOptions(org.apache.kafka.clients.admin.DescribeTopicsOptions) TopicDescription(org.apache.kafka.clients.admin.TopicDescription) ExecutionException(java.util.concurrent.ExecutionException) ClusterAuthorizationException(org.apache.kafka.common.errors.ClusterAuthorizationException) TopicAuthorizationException(org.apache.kafka.common.errors.TopicAuthorizationException) ConnectException(org.apache.kafka.connect.errors.ConnectException) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException) TimeoutException(org.apache.kafka.common.errors.TimeoutException) RetriableException(org.apache.kafka.connect.errors.RetriableException)

Example 74 with ConnectException

use of org.apache.kafka.connect.errors.ConnectException in project kafka by apache.

the class RestServer method initializeResources.

public void initializeResources(Herder herder) {
    log.info("Initializing REST resources");
    ResourceConfig resourceConfig = new ResourceConfig();
    resourceConfig.register(new JacksonJsonProvider());
    resourceConfig.register(new RootResource(herder));
    resourceConfig.register(new ConnectorsResource(herder, config));
    resourceConfig.register(new ConnectorPluginsResource(herder));
    resourceConfig.register(ConnectExceptionMapper.class);
    resourceConfig.property(ServerProperties.WADL_FEATURE_DISABLE, true);
    registerRestExtensions(herder, resourceConfig);
    List<String> adminListeners = config.getList(WorkerConfig.ADMIN_LISTENERS_CONFIG);
    ResourceConfig adminResourceConfig;
    if (adminListeners == null) {
        log.info("Adding admin resources to main listener");
        adminResourceConfig = resourceConfig;
        adminResourceConfig.register(new LoggingResource());
    } else if (adminListeners.size() > 0) {
        // TODO: we need to check if these listeners are same as 'listeners'
        // TODO: the following code assumes that they are different
        log.info("Adding admin resources to admin listener");
        adminResourceConfig = new ResourceConfig();
        adminResourceConfig.register(new JacksonJsonProvider());
        adminResourceConfig.register(new LoggingResource());
        adminResourceConfig.register(ConnectExceptionMapper.class);
    } else {
        log.info("Skipping adding admin resources");
        // set up adminResource but add no handlers to it
        adminResourceConfig = resourceConfig;
    }
    ServletContainer servletContainer = new ServletContainer(resourceConfig);
    ServletHolder servletHolder = new ServletHolder(servletContainer);
    List<Handler> contextHandlers = new ArrayList<>();
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    context.addServlet(servletHolder, "/*");
    contextHandlers.add(context);
    ServletContextHandler adminContext = null;
    if (adminResourceConfig != resourceConfig) {
        adminContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
        ServletHolder adminServletHolder = new ServletHolder(new ServletContainer(adminResourceConfig));
        adminContext.setContextPath("/");
        adminContext.addServlet(adminServletHolder, "/*");
        adminContext.setVirtualHosts(new String[] { "@" + ADMIN_SERVER_CONNECTOR_NAME });
        contextHandlers.add(adminContext);
    }
    String allowedOrigins = config.getString(WorkerConfig.ACCESS_CONTROL_ALLOW_ORIGIN_CONFIG);
    if (!Utils.isBlank(allowedOrigins)) {
        FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
        filterHolder.setName("cross-origin");
        filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, allowedOrigins);
        String allowedMethods = config.getString(WorkerConfig.ACCESS_CONTROL_ALLOW_METHODS_CONFIG);
        if (!Utils.isBlank(allowedMethods)) {
            filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, allowedMethods);
        }
        context.addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
    }
    String headerConfig = config.getString(WorkerConfig.RESPONSE_HTTP_HEADERS_CONFIG);
    if (!Utils.isBlank(headerConfig)) {
        configureHttpResponsHeaderFilter(context);
    }
    RequestLogHandler requestLogHandler = new RequestLogHandler();
    Slf4jRequestLogWriter slf4jRequestLogWriter = new Slf4jRequestLogWriter();
    slf4jRequestLogWriter.setLoggerName(RestServer.class.getCanonicalName());
    CustomRequestLog requestLog = new CustomRequestLog(slf4jRequestLogWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT + " %{ms}T");
    requestLogHandler.setRequestLog(requestLog);
    contextHandlers.add(new DefaultHandler());
    contextHandlers.add(requestLogHandler);
    handlers.setHandlers(contextHandlers.toArray(new Handler[0]));
    try {
        context.start();
    } catch (Exception e) {
        throw new ConnectException("Unable to initialize REST resources", e);
    }
    if (adminResourceConfig != resourceConfig) {
        try {
            log.debug("Starting admin context");
            adminContext.start();
        } catch (Exception e) {
            throw new ConnectException("Unable to initialize Admin REST resources", e);
        }
    }
    log.info("REST resources initialized; server is started and ready to handle requests");
}
Also used : RootResource(org.apache.kafka.connect.runtime.rest.resources.RootResource) ConnectorsResource(org.apache.kafka.connect.runtime.rest.resources.ConnectorsResource) FilterHolder(org.eclipse.jetty.servlet.FilterHolder) LoggingResource(org.apache.kafka.connect.runtime.rest.resources.LoggingResource) CustomRequestLog(org.eclipse.jetty.server.CustomRequestLog) ServletHolder(org.eclipse.jetty.servlet.ServletHolder) JacksonJsonProvider(com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider) ArrayList(java.util.ArrayList) ServletContextHandler(org.eclipse.jetty.servlet.ServletContextHandler) DefaultHandler(org.eclipse.jetty.server.handler.DefaultHandler) StatisticsHandler(org.eclipse.jetty.server.handler.StatisticsHandler) Handler(org.eclipse.jetty.server.Handler) RequestLogHandler(org.eclipse.jetty.server.handler.RequestLogHandler) ConnectorPluginsResource(org.apache.kafka.connect.runtime.rest.resources.ConnectorPluginsResource) ConnectExceptionMapper(org.apache.kafka.connect.runtime.rest.errors.ConnectExceptionMapper) CrossOriginFilter(org.eclipse.jetty.servlets.CrossOriginFilter) Slf4jRequestLogWriter(org.eclipse.jetty.server.Slf4jRequestLogWriter) IOException(java.io.IOException) ConfigException(org.apache.kafka.common.config.ConfigException) ConnectException(org.apache.kafka.connect.errors.ConnectException) DefaultHandler(org.eclipse.jetty.server.handler.DefaultHandler) RequestLogHandler(org.eclipse.jetty.server.handler.RequestLogHandler) ServletContainer(org.glassfish.jersey.servlet.ServletContainer) ResourceConfig(org.glassfish.jersey.server.ResourceConfig) ServletContextHandler(org.eclipse.jetty.servlet.ServletContextHandler) ConnectException(org.apache.kafka.connect.errors.ConnectException)

Example 75 with ConnectException

use of org.apache.kafka.connect.errors.ConnectException in project kafka by apache.

the class KafkaBasedLog method stop.

public void stop() {
    log.info("Stopping KafkaBasedLog for topic " + topic);
    synchronized (this) {
        stopRequested = true;
    }
    consumer.wakeup();
    try {
        thread.join();
    } catch (InterruptedException e) {
        throw new ConnectException("Failed to stop KafkaBasedLog. Exiting without cleanly shutting " + "down it's producer and consumer.", e);
    }
    try {
        producer.close();
    } catch (KafkaException e) {
        log.error("Failed to stop KafkaBasedLog producer", e);
    }
    try {
        consumer.close();
    } catch (KafkaException e) {
        log.error("Failed to stop KafkaBasedLog consumer", e);
    }
    // do not close the admin client, since we don't own it
    admin = null;
    log.info("Stopped KafkaBasedLog for topic " + topic);
}
Also used : KafkaException(org.apache.kafka.common.KafkaException) ConnectException(org.apache.kafka.connect.errors.ConnectException)

Aggregations

ConnectException (org.apache.kafka.connect.errors.ConnectException)184 HashMap (java.util.HashMap)38 IOException (java.io.IOException)28 Map (java.util.Map)28 ArrayList (java.util.ArrayList)23 Test (org.junit.Test)23 ExecutionException (java.util.concurrent.ExecutionException)22 TimeoutException (java.util.concurrent.TimeoutException)17 SQLException (java.sql.SQLException)16 SourceRecord (org.apache.kafka.connect.source.SourceRecord)14 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)14 Connector (org.apache.kafka.connect.connector.Connector)12 ConfigException (org.apache.kafka.common.config.ConfigException)11 TopicPartition (org.apache.kafka.common.TopicPartition)10 ConnectorTaskId (org.apache.kafka.connect.util.ConnectorTaskId)10 Collection (java.util.Collection)8 HashSet (java.util.HashSet)8 Set (java.util.Set)8 NotFoundException (org.apache.kafka.connect.errors.NotFoundException)8 SinkRecord (org.apache.kafka.connect.sink.SinkRecord)8