/**
* Copyright 2015 Confluent Inc.
*
* Licensed 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 io.confluent.kafkarest;
import org.apache.avro.SchemaParseException;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.errors.RetriableException;
import javax.ws.rs.core.Response;
import io.confluent.rest.exceptions.RestConstraintViolationException;
import io.confluent.rest.exceptions.RestException;
import io.confluent.rest.exceptions.RestNotFoundException;
import io.confluent.rest.exceptions.RestServerErrorException;
import kafka.common.InvalidConfigException;
public class Errors {
public static final String TOPIC_NOT_FOUND_MESSAGE = "Topic not found.";
public static final int TOPIC_NOT_FOUND_ERROR_CODE = 40401;
public static RestException topicNotFoundException() {
return new RestNotFoundException(TOPIC_NOT_FOUND_MESSAGE, TOPIC_NOT_FOUND_ERROR_CODE);
}
public static final String PARTITION_NOT_FOUND_MESSAGE = "Partition not found.";
public static final int PARTITION_NOT_FOUND_ERROR_CODE = 40402;
public static RestException partitionNotFoundException() {
return new RestNotFoundException(PARTITION_NOT_FOUND_MESSAGE, PARTITION_NOT_FOUND_ERROR_CODE);
}
public static final String CONSUMER_INSTANCE_NOT_FOUND_MESSAGE = "Consumer instance not found.";
public static final int CONSUMER_INSTANCE_NOT_FOUND_ERROR_CODE = 40403;
public static RestException consumerInstanceNotFoundException() {
return new RestNotFoundException(
CONSUMER_INSTANCE_NOT_FOUND_MESSAGE,
CONSUMER_INSTANCE_NOT_FOUND_ERROR_CODE
);
}
public static final String LEADER_NOT_AVAILABLE_MESSAGE = "Leader not available.";
public static final int LEADER_NOT_AVAILABLE_ERROR_CODE = 40404;
public static RestException leaderNotAvailableException() {
return new RestNotFoundException(
LEADER_NOT_AVAILABLE_MESSAGE,
LEADER_NOT_AVAILABLE_ERROR_CODE
);
}
public static final String CONSUMER_FORMAT_MISMATCH_MESSAGE =
"The requested embedded data format does not match the deserializer for this consumer "
+ "instance";
public static final int CONSUMER_FORMAT_MISMATCH_ERROR_CODE = 40601;
public static RestException consumerFormatMismatch() {
return new RestException(
CONSUMER_FORMAT_MISMATCH_MESSAGE,
Response.Status.NOT_ACCEPTABLE.getStatusCode(),
CONSUMER_FORMAT_MISMATCH_ERROR_CODE
);
}
public static final String CONSUMER_ALREADY_SUBSCRIBED_MESSAGE =
"Consumer cannot subscribe the the specified target because it has already subscribed to "
+ "other topics.";
public static final int CONSUMER_ALREADY_SUBSCRIBED_ERROR_CODE = 40901;
public static RestException consumerAlreadySubscribedException() {
return new RestException(
CONSUMER_ALREADY_SUBSCRIBED_MESSAGE,
Response.Status.CONFLICT.getStatusCode(),
CONSUMER_ALREADY_SUBSCRIBED_ERROR_CODE
);
}
public static final String CONSUMER_ALREADY_EXISTS_MESSAGE =
"Consumer with specified consumer ID already exists in the specified consumer group.";
public static final int CONSUMER_ALREADY_EXISTS_ERROR_CODE = 40902;
public static RestException consumerAlreadyExistsException() {
return new RestException(
CONSUMER_ALREADY_EXISTS_MESSAGE,
Response.Status.CONFLICT.getStatusCode(),
CONSUMER_ALREADY_EXISTS_ERROR_CODE
);
}
public static final String ILLEGAL_STATE_MESSAGE = "Illegal state: ";
public static final int ILLEGAL_STATE_ERROR_CODE = 40903;
public static RestException illegalStateException(Throwable t) {
return new RestException(
ILLEGAL_STATE_MESSAGE + t.getMessage(),
Response.Status.CONFLICT.getStatusCode(),
ILLEGAL_STATE_ERROR_CODE
);
}
public static final String KEY_SCHEMA_MISSING_MESSAGE = "Request includes keys but does not "
+ "include key schema";
public static final int KEY_SCHEMA_MISSING_ERROR_CODE = 42201;
public static RestConstraintViolationException keySchemaMissingException() {
return new RestConstraintViolationException(
KEY_SCHEMA_MISSING_MESSAGE,
KEY_SCHEMA_MISSING_ERROR_CODE
);
}
public static final String VALUE_SCHEMA_MISSING_MESSAGE = "Request includes values but does not "
+ "include value schema";
public static final int VALUE_SCHEMA_MISSING_ERROR_CODE = 42202;
public static RestConstraintViolationException valueSchemaMissingException() {
return new RestConstraintViolationException(
VALUE_SCHEMA_MISSING_MESSAGE,
VALUE_SCHEMA_MISSING_ERROR_CODE
);
}
public static final String JSON_AVRO_CONVERSION_MESSAGE = "Conversion of JSON to Avro failed: ";
public static final int JSON_AVRO_CONVERSION_ERROR_CODE = 42203;
public static RestConstraintViolationException jsonAvroConversionException(Throwable t) {
return new RestConstraintViolationException(
JSON_AVRO_CONVERSION_MESSAGE + t.getMessage(),
JSON_AVRO_CONVERSION_ERROR_CODE
);
}
public static final String INVALID_CONSUMER_CONFIG_MESSAGE = "Invalid consumer configuration: ";
public static final int INVALID_CONSUMER_CONFIG_ERROR_CODE = 42204;
public static RestConstraintViolationException invalidConsumerConfigException(
InvalidConfigException e
) {
return new RestConstraintViolationException(
INVALID_CONSUMER_CONFIG_MESSAGE + e.getMessage(),
INVALID_CONSUMER_CONFIG_ERROR_CODE
);
}
public static final String INVALID_SCHEMA_MESSAGE = "Invalid schema: ";
public static final int INVALID_SCHEMA_ERROR_CODE = 42205;
public static RestConstraintViolationException invalidSchemaException(
SchemaParseException e
) {
return new RestConstraintViolationException(
INVALID_SCHEMA_MESSAGE + e.getMessage(),
INVALID_SCHEMA_ERROR_CODE
);
}
public static final String ZOOKEEPER_ERROR_MESSAGE = "Zookeeper error: ";
public static final int ZOOKEEPER_ERROR_ERROR_CODE = 50001;
// This is a catch-all for Kafka exceptions that can't otherwise be easily classified. For
// producer operations this will be embedded in the per-message response. For consumer errors,
// these are returned in the standard error format
public static final String KAFKA_ERROR_MESSAGE = "Kafka error: ";
public static final int KAFKA_ERROR_ERROR_CODE = 50002;
public static RestServerErrorException kafkaErrorException(Throwable e) {
return new RestServerErrorException(
KAFKA_ERROR_MESSAGE + e.getMessage(),
KAFKA_ERROR_ERROR_CODE
);
}
public static final String KAFKA_RETRIABLE_ERROR_MESSAGE = "Retriable Kafka error: ";
public static final int KAFKA_RETRIABLE_ERROR_ERROR_CODE = 50003;
public static RestServerErrorException kafkaRetriableErrorException(Throwable e) {
return new RestServerErrorException(
KAFKA_RETRIABLE_ERROR_MESSAGE + e.getMessage(),
KAFKA_RETRIABLE_ERROR_ERROR_CODE
);
}
public static final String NO_SSL_SUPPORT_MESSAGE =
"Only SSL endpoints were found for the broker, but SSL is not currently supported.";
public static final int NO_SSL_SUPPORT_ERROR_CODE = 50101;
public static RestServerErrorException noSslSupportException() {
return new RestServerErrorException(
NO_SSL_SUPPORT_MESSAGE,
NO_SSL_SUPPORT_ERROR_CODE
);
}
public static final String NO_SIMPLE_CONSUMER_AVAILABLE_ERROR_MESSAGE =
"No SimpleConsumer is available at the time in the pool. The request can be retried. "
+ "You can increase the pool size or the pool timeout to avoid this error in the future.";
public static final int NO_SIMPLE_CONSUMER_AVAILABLE_ERROR_CODE = 50301;
public static RestServerErrorException simpleConsumerPoolTimeoutException() {
return new RestServerErrorException(
NO_SIMPLE_CONSUMER_AVAILABLE_ERROR_MESSAGE,
NO_SIMPLE_CONSUMER_AVAILABLE_ERROR_CODE
);
}
public static final String UNEXPECTED_PRODUCER_EXCEPTION
= "Unexpected non-Kafka exception returned by Kafka";
public static int codeFromProducerException(Throwable e) {
if (e instanceof RetriableException) {
return KAFKA_RETRIABLE_ERROR_ERROR_CODE;
} else if (e instanceof KafkaException) {
return KAFKA_ERROR_ERROR_CODE;
} else {
// We shouldn't see any non-Kafka exceptions, but this covers us in case we do see an
// unexpected error. In that case we fail the entire request -- this loses information
// since some messages may have been produced correctly, but is the right thing to do from
// a REST perspective since there was an internal error with the service while processing
// the request.
throw new RestServerErrorException(UNEXPECTED_PRODUCER_EXCEPTION,
RestServerErrorException.DEFAULT_ERROR_CODE, e
);
}
}
}