use of io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString in project schema-registry by confluentinc.
the class LeaderElectorTest method testRegistrationOnLeaderFollowerClusters.
@Test
public /**
* Test registration of schemas and fetching by id when a 'leader cluster' and 'follower cluster'
* is present. (follwer cluster == all nodes have leaderEligibility false)
*
* If only followers are alive, registration should fail. If both follower and leader cluster are
* alive, registration should succeed.
*
* Fetching by id should succeed in all configurations.
*/
void testRegistrationOnLeaderFollowerClusters() throws Exception {
int numFollowers = 4;
int numLeaders = 4;
int numSchemas = 5;
String subject = "testSubject";
List<String> schemas = TestUtils.getRandomCanonicalAvroString(numSchemas);
List<Integer> ids = new ArrayList<Integer>();
Set<RestApp> followerApps = new HashSet<RestApp>();
RestApp aFollower = null;
for (int i = 0; i < numFollowers; i++) {
RestApp follower = new RestApp(choosePort(), zkConnect(), bootstrapServers(), KAFKASTORE_TOPIC, CompatibilityLevel.NONE.name, false, null);
followerApps.add(follower);
follower.start();
aFollower = follower;
}
// Sanity check
assertNotNull(aFollower);
// Try to register schemas to a follower - should fail
boolean successfullyRegistered = false;
try {
aFollower.restClient.registerSchema(schemas.get(0), subject);
successfullyRegistered = true;
} catch (RestClientException e) {
// registration should fail
}
assertFalse("Should not be possible to register with no leaders present.", successfullyRegistered);
// Make a leader-eligible 'cluster'
final Set<RestApp> leaderApps = new HashSet<RestApp>();
RestApp aLeader = null;
for (int i = 0; i < numLeaders; i++) {
RestApp leader = new RestApp(choosePort(), zkConnect(), bootstrapServers(), KAFKASTORE_TOPIC, CompatibilityLevel.NONE.name, true, null);
leaderApps.add(leader);
leader.start();
aLeader = leader;
}
assertNotNull(aLeader);
// Try to register to a leader cluster node - should succeed
try {
for (String schema : schemas) {
ids.add(aLeader.restClient.registerSchema(schema, subject));
}
} catch (RestClientException e) {
fail("It should be possible to register schemas when a leader cluster is present.");
}
// Try to register to a follower cluster node - should succeed
String anotherSchema = TestUtils.getRandomCanonicalAvroString(1).get(0);
try {
ids.add(aFollower.restClient.registerSchema(anotherSchema, subject));
} catch (RestClientException e) {
fail("Should be possible register a schema through follower cluster.");
}
// Verify all ids can be fetched
try {
for (int id : ids) {
waitUntilIdExists(aFollower.restClient, id, String.format("Should be possible to fetch id %d from this follower.", id));
waitUntilIdExists(aLeader.restClient, id, String.format("Should be possible to fetch id %d from this leader.", id));
SchemaString followerResponse = aFollower.restClient.getId(id);
SchemaString leaderResponse = aLeader.restClient.getId(id);
assertEquals("Leader and follower responded with different schemas when queried with the same id.", followerResponse.getSchemaString(), leaderResponse.getSchemaString());
}
} catch (RestClientException e) {
fail("Expected ids were not found in the schema registry.");
}
// Stop everything in the leader cluster
while (leaderApps.size() > 0) {
RestApp leader = findLeader(leaderApps);
leaderApps.remove(leader);
leader.stop();
waitUntilLeaderElectionCompletes(leaderApps);
}
// Try to register a new schema - should fail
anotherSchema = TestUtils.getRandomCanonicalAvroString(1).get(0);
successfullyRegistered = false;
try {
aFollower.restClient.registerSchema(anotherSchema, subject);
successfullyRegistered = true;
} catch (RestClientException e) {
// should fail
}
assertFalse("Should not be possible to register with no leaders present.", successfullyRegistered);
// Try fetching preregistered ids from followers - should succeed
try {
for (int id : ids) {
SchemaString schemaString = aFollower.restClient.getId(id);
}
List<Integer> versions = aFollower.restClient.getAllVersions(subject);
assertEquals("Number of ids should match number of versions.", ids.size(), versions.size());
} catch (RestClientException e) {
fail("Should be possible to fetch registered schemas even with no leaders present.");
}
for (RestApp follower : followerApps) {
follower.stop();
}
}
use of io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString in project schema-registry by confluentinc.
the class RestApiTest method testSchemaReferencesMultipleLevels.
@Test
public void testSchemaReferencesMultipleLevels() throws Exception {
String root = "[\"myavro.BudgetDecreased\",\"myavro.BudgetUpdated\"]";
String ref1 = "{\n" + " \"type\" : \"record\",\n" + " \"name\" : \"BudgetDecreased\",\n" + " \"namespace\" : \"myavro\",\n" + " \"fields\" : [ {\n" + " \"name\" : \"buyerId\",\n" + " \"type\" : \"long\"\n" + " }, {\n" + " \"name\" : \"currency\",\n" + " \"type\" : {\n" + " \"type\" : \"myavro.currencies.Currency\"" + " }\n" + " }, {\n" + " \"name\" : \"amount\",\n" + " \"type\" : \"double\"\n" + " } ]\n" + "}";
String ref2 = "{\n" + " \"type\" : \"record\",\n" + " \"name\" : \"BudgetUpdated\",\n" + " \"namespace\" : \"myavro\",\n" + " \"fields\" : [ {\n" + " \"name\" : \"buyerId\",\n" + " \"type\" : \"long\"\n" + " }, {\n" + " \"name\" : \"currency\",\n" + " \"type\" : {\n" + " \"type\" : \"myavro.currencies.Currency\"" + " }\n" + " }, {\n" + " \"name\" : \"updatedValue\",\n" + " \"type\" : \"double\"\n" + " } ]\n" + "}";
String sharedRef = "{\n" + " \"type\" : \"enum\",\n" + " \"name\" : \"Currency\",\n" + " \"namespace\" : \"myavro.currencies\",\n" + " \"symbols\" : [ \"EUR\", \"USD\" ]\n" + " }\n";
TestUtils.registerAndVerifySchema(restApp.restClient, new AvroSchema(sharedRef).canonicalString(), 1, "shared");
RegisterSchemaRequest request = new RegisterSchemaRequest();
request.setSchema(ref1);
SchemaReference ref = new SchemaReference("myavro.currencies.Currency", "shared", 1);
request.setReferences(Collections.singletonList(ref));
int registeredId = restApp.restClient.registerSchema(request, "ref1", false);
assertEquals("Registering a new schema should succeed", 2, registeredId);
request = new RegisterSchemaRequest();
request.setSchema(ref2);
ref = new SchemaReference("myavro.currencies.Currency", "shared", 1);
request.setReferences(Collections.singletonList(ref));
registeredId = restApp.restClient.registerSchema(request, "ref2", false);
assertEquals("Registering a new schema should succeed", 3, registeredId);
request = new RegisterSchemaRequest();
request.setSchema(root);
SchemaReference r1 = new SchemaReference("myavro.BudgetDecreased", "ref1", 1);
SchemaReference r2 = new SchemaReference("myavro.BudgetUpdated", "ref2", 1);
request.setReferences(Arrays.asList(r1, r2));
registeredId = restApp.restClient.registerSchema(request, "root", false);
assertEquals("Registering a new schema should succeed", 4, registeredId);
SchemaString schemaString = restApp.restClient.getId(4);
// the newly registered schema should be immediately readable on the leader
assertEquals("Registered schema should be found", root, schemaString.getSchemaString());
assertEquals("Schema references should be found", Arrays.asList(r1, r2), schemaString.getReferences());
}
use of io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString in project schema-registry by confluentinc.
the class RestApiTest method testRegisterBadDefault.
@Test
public void testRegisterBadDefault() throws Exception {
String subject = "testSubject";
String schemaString = "{\"type\":\"record\"," + "\"name\":\"myrecord\"," + "\"fields\":" + "[{\"type\":\"string\",\"default\":null,\"name\":" + "\"f" + "\"}]}";
String schema = AvroUtils.parseSchema(schemaString).canonicalString();
try {
restApp.restClient.testCompatibility(schema, subject, "latest");
fail("Testing compatibility for schema with invalid default should fail with " + Errors.INVALID_SCHEMA_ERROR_CODE + " (invalid schema)");
} catch (RestClientException rce) {
assertEquals("Invalid schema", Errors.INVALID_SCHEMA_ERROR_CODE, rce.getErrorCode());
}
try {
restApp.restClient.registerSchema(schema, subject);
fail("Registering schema with invalid default should fail with " + Errors.INVALID_SCHEMA_ERROR_CODE + " (invalid schema)");
} catch (RestClientException rce) {
assertEquals("Invalid schema", Errors.INVALID_SCHEMA_ERROR_CODE, rce.getErrorCode());
}
}
use of io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString in project schema-registry by confluentinc.
the class RestApiTest method getProtobufSchemaWithDependencies.
public static Map<String, String> getProtobufSchemaWithDependencies() {
Map<String, String> schemas = new HashMap<>();
String meta = ResourceLoader.DEFAULT.toString("confluent/meta.proto");
schemas.put("confluent/meta.proto", meta);
String reference = "syntax = \"proto3\";\npackage io.confluent.kafka.serializers.protobuf.test;\n\n" + "message ReferencedMessage {\n string ref_id = 1;\n bool is_active = 2;\n}\n";
schemas.put("ref.proto", reference);
String schemaString = "syntax = \"proto3\";\n" + "package io.confluent.kafka.serializers.protobuf.test;\n" + "\n" + "import \"ref.proto\";\n" + "import \"confluent/meta.proto\";\n" + "\n" + "message ReferrerMessage {\n" + " option (confluent.message_meta) = {\n" + " doc: \"ReferrerMessage\"\n" + " };\n" + "\n" + " string root_id = 1;\n" + " .io.confluent.kafka.serializers.protobuf.test.ReferencedMessage ref = 2 [(confluent.field_meta) = {\n" + " doc: \"ReferencedMessage\"\n" + " }];\n" + "}\n";
schemas.put("root.proto", schemaString);
return schemas;
}
use of io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString in project schema-registry by confluentinc.
the class SchemasResource method getSchema.
@GET
@Path("/ids/{id}")
@Operation(summary = "Get the schema string identified by the input ID.", responses = { @ApiResponse(responseCode = "404", description = "Error code 40403 -- Schema not found\n"), @ApiResponse(responseCode = "500", description = "Error code 50001 -- Error in the backend data store\n") })
@PerformanceMetric("schemas.ids.get-schema")
public SchemaString getSchema(@Parameter(description = "Globally unique identifier of the schema", required = true) @PathParam("id") Integer id, @Parameter(description = "Name of the subject") @QueryParam("subject") String subject, @Parameter(description = "Desired output format, dependent on schema type") @DefaultValue("") @QueryParam("format") String format, @Parameter(description = "Whether to fetch the maximum schema identifier that exists") @DefaultValue("false") @QueryParam("fetchMaxId") boolean fetchMaxId) {
SchemaString schema;
String errorMessage = "Error while retrieving schema with id " + id + " from the schema " + "registry";
try {
schema = schemaRegistry.get(id, subject, format, fetchMaxId);
} catch (SchemaRegistryStoreException e) {
log.debug(errorMessage, e);
throw Errors.storeException(errorMessage, e);
} catch (SchemaRegistryException e) {
throw Errors.schemaRegistryException(errorMessage, e);
}
if (schema == null) {
throw Errors.schemaNotFoundException(id);
}
return schema;
}
Aggregations