You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by jg...@apache.org on 2019/01/22 16:50:13 UTC

[kafka] branch 2.0 updated: MINOR: Cleanup handling of mixed transactional/idempotent records (#6172)

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

jgus pushed a commit to branch 2.0
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/2.0 by this push:
     new fef588d  MINOR: Cleanup handling of mixed transactional/idempotent records (#6172)
fef588d is described below

commit fef588d0484afeecf6d8c8545d428c99b4a72e09
Author: Jason Gustafson <ja...@confluent.io>
AuthorDate: Tue Jan 22 08:35:14 2019 -0800

    MINOR: Cleanup handling of mixed transactional/idempotent records (#6172)
    
    Reviewers: Rajini Sivaram <ra...@googlemail.com>, Ismael Juma <is...@juma.me.uk>, Colin Patrick McCabe <co...@cmccabe.xyz>
---
 .../common/message/AddOffsetsToTxnRequestData.java |  203 +++
 .../message/AddOffsetsToTxnResponseData.java       |  152 ++
 .../message/AddPartitionsToTxnRequestData.java     |  439 +++++
 .../message/AddPartitionsToTxnResponseData.java    |  561 ++++++
 .../common/message/AlterConfigsRequestData.java    |  591 +++++++
 .../common/message/AlterConfigsResponseData.java   |  363 ++++
 .../message/AlterReplicaLogDirsRequestData.java    |  576 ++++++
 .../message/AlterReplicaLogDirsResponseData.java   |  470 +++++
 .../kafka/common/message/ApiMessageFactory.java    |  398 +++++
 .../common/message/ApiVersionsRequestData.java     |  112 ++
 .../common/message/ApiVersionsResponseData.java    |  421 +++++
 .../message/ControlledShutdownRequestData.java     |  172 ++
 .../message/ControlledShutdownResponseData.java    |  374 ++++
 .../common/message/CreateAclsRequestData.java      |  436 +++++
 .../common/message/CreateAclsResponseData.java     |  318 ++++
 .../message/CreateDelegationTokenRequestData.java  |  321 ++++
 .../message/CreateDelegationTokenResponseData.java |  311 ++++
 .../message/CreatePartitionsRequestData.java       |  539 ++++++
 .../message/CreatePartitionsResponseData.java      |  343 ++++
 .../common/message/CreateTopicsRequestData.java    |  884 +++++++++
 .../common/message/CreateTopicsResponseData.java   |  435 +++++
 .../common/message/DeleteAclsRequestData.java      |  442 +++++
 .../common/message/DeleteAclsResponseData.java     |  692 ++++++++
 .../common/message/DeleteGroupsRequestData.java    |  172 ++
 .../common/message/DeleteGroupsResponseData.java   |  364 ++++
 .../common/message/DeleteRecordsRequestData.java   |  470 +++++
 .../common/message/DeleteRecordsResponseData.java  |  490 +++++
 .../common/message/DeleteTopicsRequestData.java    |  198 +++
 .../common/message/DeleteTopicsResponseData.java   |  350 ++++
 .../common/message/DescribeAclsRequestData.java    |  301 ++++
 .../common/message/DescribeAclsResponseData.java   |  637 +++++++
 .../common/message/DescribeConfigsRequestData.java |  416 +++++
 .../message/DescribeConfigsResponseData.java       |  918 ++++++++++
 .../DescribeDelegationTokenRequestData.java        |  317 ++++
 .../DescribeDelegationTokenResponseData.java       |  633 +++++++
 .../common/message/DescribeGroupsRequestData.java  |  175 ++
 .../common/message/DescribeGroupsResponseData.java |  670 +++++++
 .../common/message/DescribeLogDirsRequestData.java |  345 ++++
 .../message/DescribeLogDirsResponseData.java       |  689 ++++++++
 .../kafka/common/message/EndTxnRequestData.java    |  198 +++
 .../kafka/common/message/EndTxnResponseData.java   |  152 ++
 .../message/ExpireDelegationTokenRequestData.java  |  155 ++
 .../message/ExpireDelegationTokenResponseData.java |  172 ++
 .../kafka/common/message/FetchRequestData.java     | 1143 ++++++++++++
 .../kafka/common/message/FetchResponseData.java    | 1028 +++++++++++
 .../common/message/FindCoordinatorRequestData.java |  183 ++
 .../message/FindCoordinatorResponseData.java       |  282 +++
 .../kafka/common/message/HeartbeatRequestData.java |  186 ++
 .../common/message/HeartbeatResponseData.java      |  172 ++
 .../common/message/InitProducerIdRequestData.java  |  160 ++
 .../common/message/InitProducerIdResponseData.java |  192 ++
 .../kafka/common/message/JoinGroupRequestData.java |  501 ++++++
 .../common/message/JoinGroupResponseData.java      |  474 +++++
 .../common/message/LeaderAndIsrRequestData.java    | 1388 +++++++++++++++
 .../common/message/LeaderAndIsrResponseData.java   |  342 ++++
 .../common/message/LeaveGroupRequestData.java      |  166 ++
 .../common/message/LeaveGroupResponseData.java     |  172 ++
 .../common/message/ListGroupsRequestData.java      |  112 ++
 .../common/message/ListGroupsResponseData.java     |  365 ++++
 .../common/message/ListOffsetRequestData.java      |  650 +++++++
 .../common/message/ListOffsetResponseData.java     |  728 ++++++++
 .../kafka/common/message/MetadataRequestData.java  |  373 ++++
 .../kafka/common/message/MetadataResponseData.java | 1293 ++++++++++++++
 .../common/message/OffsetCommitRequestData.java    |  776 ++++++++
 .../common/message/OffsetCommitResponseData.java   |  532 ++++++
 .../common/message/OffsetFetchRequestData.java     |  398 +++++
 .../common/message/OffsetFetchResponseData.java    |  666 +++++++
 .../message/OffsetForLeaderEpochRequestData.java   |  504 ++++++
 .../message/OffsetForLeaderEpochResponseData.java  |  562 ++++++
 .../kafka/common/message/ProduceRequestData.java   |  600 +++++++
 .../kafka/common/message/ProduceResponseData.java  |  656 +++++++
 .../message/RenewDelegationTokenRequestData.java   |  155 ++
 .../message/RenewDelegationTokenResponseData.java  |  172 ++
 .../kafka/common/message/RequestHeaderData.java    |  195 ++
 .../kafka/common/message/ResponseHeaderData.java   |  129 ++
 .../message/SaslAuthenticateRequestData.java       |  135 ++
 .../message/SaslAuthenticateResponseData.java      |  227 +++
 .../common/message/SaslHandshakeRequestData.java   |  138 ++
 .../common/message/SaslHandshakeResponseData.java  |  192 ++
 .../common/message/StopReplicaRequestData.java     |  657 +++++++
 .../common/message/StopReplicaResponseData.java    |  336 ++++
 .../kafka/common/message/SyncGroupRequestData.java |  375 ++++
 .../common/message/SyncGroupResponseData.java      |  196 ++
 .../common/message/TxnOffsetCommitRequestData.java |  626 +++++++
 .../message/TxnOffsetCommitResponseData.java       |  479 +++++
 .../common/message/UpdateMetadataRequestData.java  | 1868 ++++++++++++++++++++
 .../common/message/UpdateMetadataResponseData.java |  144 ++
 .../common/message/WriteTxnMarkersRequestData.java |  534 ++++++
 .../message/WriteTxnMarkersResponseData.java       |  592 +++++++
 .../kafka/common/requests/ProduceRequest.java      |   16 +-
 .../clients/producer/internals/SenderTest.java     |   14 +-
 .../kafka/common/requests/ProduceRequestTest.java  |   57 +-
 core/src/main/scala/kafka/server/KafkaApis.scala   |    8 +-
 93 files changed, 39202 insertions(+), 22 deletions(-)

diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnRequestData.java
new file mode 100644
index 0000000..8771eda
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnRequestData.java
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class AddOffsetsToTxnRequestData implements ApiMessage {
+    private String transactionalId;
+    private long producerId;
+    private short producerEpoch;
+    private String groupId;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("transactional_id", Type.STRING, "The transactional id corresponding to the transaction."),
+            new Field("producer_id", Type.INT64, "Current producer id in use by the transactional id."),
+            new Field("producer_epoch", Type.INT16, "Current epoch associated with the producer id."),
+            new Field("group_id", Type.STRING, "The unique group identifier.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AddOffsetsToTxnRequestData(Readable readable, short version) {
+        read(readable, version);
+    }
+    
+    public AddOffsetsToTxnRequestData(Struct struct, short version) {
+        fromStruct(struct, version);
+    }
+    
+    public AddOffsetsToTxnRequestData() {
+        this.transactionalId = "";
+        this.producerId = 0L;
+        this.producerEpoch = (short) 0;
+        this.groupId = "";
+    }
+    
+    @Override
+    public short apiKey() {
+        return 25;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.transactionalId = readable.readNullableString();
+        this.producerId = readable.readLong();
+        this.producerEpoch = readable.readShort();
+        this.groupId = readable.readNullableString();
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeString(transactionalId);
+        writable.writeLong(producerId);
+        writable.writeShort(producerEpoch);
+        writable.writeString(groupId);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.transactionalId = struct.getString("transactional_id");
+        this.producerId = struct.getLong("producer_id");
+        this.producerEpoch = struct.getShort("producer_epoch");
+        this.groupId = struct.getString("group_id");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("transactional_id", this.transactionalId);
+        struct.set("producer_id", this.producerId);
+        struct.set("producer_epoch", this.producerEpoch);
+        struct.set("group_id", this.groupId);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(transactionalId);
+        size += 8;
+        size += 2;
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(groupId);
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AddOffsetsToTxnRequestData)) return false;
+        AddOffsetsToTxnRequestData other = (AddOffsetsToTxnRequestData) obj;
+        if (this.transactionalId == null) {
+            if (other.transactionalId != null) return false;
+        } else {
+            if (!this.transactionalId.equals(other.transactionalId)) return false;
+        }
+        if (producerId != other.producerId) return false;
+        if (producerEpoch != other.producerEpoch) return false;
+        if (this.groupId == null) {
+            if (other.groupId != null) return false;
+        } else {
+            if (!this.groupId.equals(other.groupId)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (transactionalId == null ? 0 : transactionalId.hashCode());
+        hashCode = 31 * hashCode + ((int) (producerId >> 32) ^ (int) producerId);
+        hashCode = 31 * hashCode + producerEpoch;
+        hashCode = 31 * hashCode + (groupId == null ? 0 : groupId.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AddOffsetsToTxnRequestData("
+            + "transactionalId='" + transactionalId + "'"
+            + ", producerId=" + producerId
+            + ", producerEpoch=" + producerEpoch
+            + ", groupId='" + groupId + "'"
+            + ")";
+    }
+    
+    public String transactionalId() {
+        return this.transactionalId;
+    }
+    
+    public long producerId() {
+        return this.producerId;
+    }
+    
+    public short producerEpoch() {
+        return this.producerEpoch;
+    }
+    
+    public String groupId() {
+        return this.groupId;
+    }
+    
+    public AddOffsetsToTxnRequestData setTransactionalId(String v) {
+        this.transactionalId = v;
+        return this;
+    }
+    
+    public AddOffsetsToTxnRequestData setProducerId(long v) {
+        this.producerId = v;
+        return this;
+    }
+    
+    public AddOffsetsToTxnRequestData setProducerEpoch(short v) {
+        this.producerEpoch = v;
+        return this;
+    }
+    
+    public AddOffsetsToTxnRequestData setGroupId(String v) {
+        this.groupId = v;
+        return this;
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnResponseData.java
new file mode 100644
index 0000000..08b51c1
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AddOffsetsToTxnResponseData.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class AddOffsetsToTxnResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private short errorCode;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "Duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("error_code", Type.INT16, "The response error code, or 0 if there was no error.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AddOffsetsToTxnResponseData(Readable readable, short version) {
+        read(readable, version);
+    }
+    
+    public AddOffsetsToTxnResponseData(Struct struct, short version) {
+        fromStruct(struct, version);
+    }
+    
+    public AddOffsetsToTxnResponseData() {
+        this.throttleTimeMs = 0;
+        this.errorCode = (short) 0;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 25;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        this.errorCode = readable.readShort();
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeShort(errorCode);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        this.errorCode = struct.getShort("error_code");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        struct.set("error_code", this.errorCode);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 2;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AddOffsetsToTxnResponseData)) return false;
+        AddOffsetsToTxnResponseData other = (AddOffsetsToTxnResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (errorCode != other.errorCode) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + errorCode;
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AddOffsetsToTxnResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", errorCode=" + errorCode
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public short errorCode() {
+        return this.errorCode;
+    }
+    
+    public AddOffsetsToTxnResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public AddOffsetsToTxnResponseData setErrorCode(short v) {
+        this.errorCode = v;
+        return this;
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnRequestData.java
new file mode 100644
index 0000000..f762a2b
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnRequestData.java
@@ -0,0 +1,439 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class AddPartitionsToTxnRequestData implements ApiMessage {
+    private String transactionalId;
+    private long producerId;
+    private short producerEpoch;
+    private AddPartitionsToTxnTopicSet topics;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("transactional_id", Type.STRING, "The transactional id corresponding to the transaction."),
+            new Field("producer_id", Type.INT64, "Current producer id in use by the transactional id."),
+            new Field("producer_epoch", Type.INT16, "Current epoch associated with the producer id."),
+            new Field("topics", new ArrayOf(AddPartitionsToTxnTopic.SCHEMA_0), "The partitions to add to the transation.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AddPartitionsToTxnRequestData(Readable readable, short version) {
+        this.topics = new AddPartitionsToTxnTopicSet(0);
+        read(readable, version);
+    }
+    
+    public AddPartitionsToTxnRequestData(Struct struct, short version) {
+        this.topics = new AddPartitionsToTxnTopicSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public AddPartitionsToTxnRequestData() {
+        this.transactionalId = "";
+        this.producerId = 0L;
+        this.producerEpoch = (short) 0;
+        this.topics = new AddPartitionsToTxnTopicSet(0);
+    }
+    
+    @Override
+    public short apiKey() {
+        return 24;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.transactionalId = readable.readNullableString();
+        this.producerId = readable.readLong();
+        this.producerEpoch = readable.readShort();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.topics.clear(0);
+            } else {
+                this.topics.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.topics.add(new AddPartitionsToTxnTopic(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeString(transactionalId);
+        writable.writeLong(producerId);
+        writable.writeShort(producerEpoch);
+        writable.writeInt(topics.size());
+        for (AddPartitionsToTxnTopic element : topics) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.transactionalId = struct.getString("transactional_id");
+        this.producerId = struct.getLong("producer_id");
+        this.producerEpoch = struct.getShort("producer_epoch");
+        {
+            Object[] nestedObjects = struct.getArray("topics");
+            this.topics = new AddPartitionsToTxnTopicSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.topics.add(new AddPartitionsToTxnTopic((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("transactional_id", this.transactionalId);
+        struct.set("producer_id", this.producerId);
+        struct.set("producer_epoch", this.producerEpoch);
+        {
+            Struct[] nestedObjects = new Struct[topics.size()];
+            int i = 0;
+            for (AddPartitionsToTxnTopic element : this.topics) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("topics", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(transactionalId);
+        size += 8;
+        size += 2;
+        size += 4;
+        for (AddPartitionsToTxnTopic element : topics) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AddPartitionsToTxnRequestData)) return false;
+        AddPartitionsToTxnRequestData other = (AddPartitionsToTxnRequestData) obj;
+        if (this.transactionalId == null) {
+            if (other.transactionalId != null) return false;
+        } else {
+            if (!this.transactionalId.equals(other.transactionalId)) return false;
+        }
+        if (producerId != other.producerId) return false;
+        if (producerEpoch != other.producerEpoch) return false;
+        if (this.topics == null) {
+            if (other.topics != null) return false;
+        } else {
+            if (!this.topics.equals(other.topics)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (transactionalId == null ? 0 : transactionalId.hashCode());
+        hashCode = 31 * hashCode + ((int) (producerId >> 32) ^ (int) producerId);
+        hashCode = 31 * hashCode + producerEpoch;
+        hashCode = 31 * hashCode + (topics == null ? 0 : topics.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AddPartitionsToTxnRequestData("
+            + "transactionalId='" + transactionalId + "'"
+            + ", producerId=" + producerId
+            + ", producerEpoch=" + producerEpoch
+            + ", topics=" + MessageUtil.deepToString(topics.iterator())
+            + ")";
+    }
+    
+    public String transactionalId() {
+        return this.transactionalId;
+    }
+    
+    public long producerId() {
+        return this.producerId;
+    }
+    
+    public short producerEpoch() {
+        return this.producerEpoch;
+    }
+    
+    public AddPartitionsToTxnTopicSet topics() {
+        return this.topics;
+    }
+    
+    public AddPartitionsToTxnRequestData setTransactionalId(String v) {
+        this.transactionalId = v;
+        return this;
+    }
+    
+    public AddPartitionsToTxnRequestData setProducerId(long v) {
+        this.producerId = v;
+        return this;
+    }
+    
+    public AddPartitionsToTxnRequestData setProducerEpoch(short v) {
+        this.producerEpoch = v;
+        return this;
+    }
+    
+    public AddPartitionsToTxnRequestData setTopics(AddPartitionsToTxnTopicSet v) {
+        this.topics = v;
+        return this;
+    }
+    
+    static public class AddPartitionsToTxnTopic implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private List<Integer> partitions;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The name of the topic."),
+                new Field("partitions", new ArrayOf(Type.INT32), "The partition indexes to add to the transaction")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AddPartitionsToTxnTopic(Readable readable, short version) {
+            this.partitions = new ArrayList<Integer>();
+            read(readable, version);
+        }
+        
+        public AddPartitionsToTxnTopic(Struct struct, short version) {
+            this.partitions = new ArrayList<Integer>();
+            fromStruct(struct, version);
+        }
+        
+        public AddPartitionsToTxnTopic() {
+            this.name = "";
+            this.partitions = new ArrayList<Integer>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.partitions.clear();
+                } else {
+                    this.partitions.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.partitions.add(readable.readInt());
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeInt(partitions.size());
+            for (Integer element : partitions) {
+                writable.writeInt(element);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            {
+                Object[] nestedObjects = struct.getArray("partitions");
+                this.partitions = new ArrayList<Integer>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.partitions.add((Integer) nestedObject);
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            {
+                Integer[] nestedObjects = new Integer[partitions.size()];
+                int i = 0;
+                for (Integer element : this.partitions) {
+                    nestedObjects[i++] = element;
+                }
+                struct.set("partitions", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 4;
+            size += partitions.size() * 4;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AddPartitionsToTxnTopic)) return false;
+            AddPartitionsToTxnTopic other = (AddPartitionsToTxnTopic) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AddPartitionsToTxnTopic("
+                + "name='" + name + "'"
+                + ", partitions=" + MessageUtil.deepToString(partitions.iterator())
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public List<Integer> partitions() {
+            return this.partitions;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AddPartitionsToTxnTopic setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public AddPartitionsToTxnTopic setPartitions(List<Integer> v) {
+            this.partitions = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class AddPartitionsToTxnTopicSet extends ImplicitLinkedHashMultiSet<AddPartitionsToTxnTopic> {
+        public AddPartitionsToTxnTopicSet() {
+            super();
+        }
+        
+        public AddPartitionsToTxnTopicSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AddPartitionsToTxnTopicSet(Iterator<AddPartitionsToTxnTopic> iterator) {
+            super(iterator);
+        }
+        
+        public AddPartitionsToTxnTopic find(String name) {
+            AddPartitionsToTxnTopic key = new AddPartitionsToTxnTopic();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<AddPartitionsToTxnTopic> findAll(String name) {
+            AddPartitionsToTxnTopic key = new AddPartitionsToTxnTopic();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnResponseData.java
new file mode 100644
index 0000000..458aee9
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AddPartitionsToTxnResponseData.java
@@ -0,0 +1,561 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class AddPartitionsToTxnResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private AddPartitionsToTxnTopicResultSet results;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "Duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("results", new ArrayOf(AddPartitionsToTxnTopicResult.SCHEMA_0), "The results for each topic.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AddPartitionsToTxnResponseData(Readable readable, short version) {
+        this.results = new AddPartitionsToTxnTopicResultSet(0);
+        read(readable, version);
+    }
+    
+    public AddPartitionsToTxnResponseData(Struct struct, short version) {
+        this.results = new AddPartitionsToTxnTopicResultSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public AddPartitionsToTxnResponseData() {
+        this.throttleTimeMs = 0;
+        this.results = new AddPartitionsToTxnTopicResultSet(0);
+    }
+    
+    @Override
+    public short apiKey() {
+        return 24;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.results.clear(0);
+            } else {
+                this.results.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.results.add(new AddPartitionsToTxnTopicResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(results.size());
+        for (AddPartitionsToTxnTopicResult element : results) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("results");
+            this.results = new AddPartitionsToTxnTopicResultSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.results.add(new AddPartitionsToTxnTopicResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[results.size()];
+            int i = 0;
+            for (AddPartitionsToTxnTopicResult element : this.results) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("results", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (AddPartitionsToTxnTopicResult element : results) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AddPartitionsToTxnResponseData)) return false;
+        AddPartitionsToTxnResponseData other = (AddPartitionsToTxnResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.results == null) {
+            if (other.results != null) return false;
+        } else {
+            if (!this.results.equals(other.results)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (results == null ? 0 : results.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AddPartitionsToTxnResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", results=" + MessageUtil.deepToString(results.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public AddPartitionsToTxnTopicResultSet results() {
+        return this.results;
+    }
+    
+    public AddPartitionsToTxnResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public AddPartitionsToTxnResponseData setResults(AddPartitionsToTxnTopicResultSet v) {
+        this.results = v;
+        return this;
+    }
+    
+    static public class AddPartitionsToTxnTopicResult implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private AddPartitionsToTxnPartitionResultSet results;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("results", new ArrayOf(AddPartitionsToTxnPartitionResult.SCHEMA_0), "The results for each partition")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AddPartitionsToTxnTopicResult(Readable readable, short version) {
+            this.results = new AddPartitionsToTxnPartitionResultSet(0);
+            read(readable, version);
+        }
+        
+        public AddPartitionsToTxnTopicResult(Struct struct, short version) {
+            this.results = new AddPartitionsToTxnPartitionResultSet(0);
+            fromStruct(struct, version);
+        }
+        
+        public AddPartitionsToTxnTopicResult() {
+            this.name = "";
+            this.results = new AddPartitionsToTxnPartitionResultSet(0);
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.results.clear(0);
+                } else {
+                    this.results.clear(arrayLength);
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.results.add(new AddPartitionsToTxnPartitionResult(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeInt(results.size());
+            for (AddPartitionsToTxnPartitionResult element : results) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            {
+                Object[] nestedObjects = struct.getArray("results");
+                this.results = new AddPartitionsToTxnPartitionResultSet(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.results.add(new AddPartitionsToTxnPartitionResult((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            {
+                Struct[] nestedObjects = new Struct[results.size()];
+                int i = 0;
+                for (AddPartitionsToTxnPartitionResult element : this.results) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("results", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 4;
+            for (AddPartitionsToTxnPartitionResult element : results) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AddPartitionsToTxnTopicResult)) return false;
+            AddPartitionsToTxnTopicResult other = (AddPartitionsToTxnTopicResult) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AddPartitionsToTxnTopicResult("
+                + "name='" + name + "'"
+                + ", results=" + MessageUtil.deepToString(results.iterator())
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public AddPartitionsToTxnPartitionResultSet results() {
+            return this.results;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AddPartitionsToTxnTopicResult setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public AddPartitionsToTxnTopicResult setResults(AddPartitionsToTxnPartitionResultSet v) {
+            this.results = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    static public class AddPartitionsToTxnPartitionResult implements Message, ImplicitLinkedHashMultiSet.Element {
+        private int partitionIndex;
+        private short errorCode;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("partition_index", Type.INT32, "The partition indexes."),
+                new Field("error_code", Type.INT16, "The response error code.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AddPartitionsToTxnPartitionResult(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public AddPartitionsToTxnPartitionResult(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public AddPartitionsToTxnPartitionResult() {
+            this.partitionIndex = 0;
+            this.errorCode = (short) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.partitionIndex = readable.readInt();
+            this.errorCode = readable.readShort();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeInt(partitionIndex);
+            writable.writeShort(errorCode);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.partitionIndex = struct.getInt("partition_index");
+            this.errorCode = struct.getShort("error_code");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("partition_index", this.partitionIndex);
+            struct.set("error_code", this.errorCode);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 4;
+            size += 2;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AddPartitionsToTxnPartitionResult)) return false;
+            AddPartitionsToTxnPartitionResult other = (AddPartitionsToTxnPartitionResult) obj;
+            if (partitionIndex != other.partitionIndex) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + partitionIndex;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AddPartitionsToTxnPartitionResult("
+                + "partitionIndex=" + partitionIndex
+                + ", errorCode=" + errorCode
+                + ")";
+        }
+        
+        public int partitionIndex() {
+            return this.partitionIndex;
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AddPartitionsToTxnPartitionResult setPartitionIndex(int v) {
+            this.partitionIndex = v;
+            return this;
+        }
+        
+        public AddPartitionsToTxnPartitionResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class AddPartitionsToTxnPartitionResultSet extends ImplicitLinkedHashMultiSet<AddPartitionsToTxnPartitionResult> {
+        public AddPartitionsToTxnPartitionResultSet() {
+            super();
+        }
+        
+        public AddPartitionsToTxnPartitionResultSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AddPartitionsToTxnPartitionResultSet(Iterator<AddPartitionsToTxnPartitionResult> iterator) {
+            super(iterator);
+        }
+        
+        public AddPartitionsToTxnPartitionResult find(int partitionIndex) {
+            AddPartitionsToTxnPartitionResult key = new AddPartitionsToTxnPartitionResult();
+            key.setPartitionIndex(partitionIndex);
+            return find(key);
+        }
+        
+        public List<AddPartitionsToTxnPartitionResult> findAll(int partitionIndex) {
+            AddPartitionsToTxnPartitionResult key = new AddPartitionsToTxnPartitionResult();
+            key.setPartitionIndex(partitionIndex);
+            return findAll(key);
+        }
+        
+    }
+    
+    public static class AddPartitionsToTxnTopicResultSet extends ImplicitLinkedHashMultiSet<AddPartitionsToTxnTopicResult> {
+        public AddPartitionsToTxnTopicResultSet() {
+            super();
+        }
+        
+        public AddPartitionsToTxnTopicResultSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AddPartitionsToTxnTopicResultSet(Iterator<AddPartitionsToTxnTopicResult> iterator) {
+            super(iterator);
+        }
+        
+        public AddPartitionsToTxnTopicResult find(String name) {
+            AddPartitionsToTxnTopicResult key = new AddPartitionsToTxnTopicResult();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<AddPartitionsToTxnTopicResult> findAll(String name) {
+            AddPartitionsToTxnTopicResult key = new AddPartitionsToTxnTopicResult();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsRequestData.java
new file mode 100644
index 0000000..347301a
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsRequestData.java
@@ -0,0 +1,591 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class AlterConfigsRequestData implements ApiMessage {
+    private AlterConfigsResourceSet resources;
+    private boolean validateOnly;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("resources", new ArrayOf(AlterConfigsResource.SCHEMA_0), "The updates for each resource."),
+            new Field("validate_only", Type.BOOLEAN, "True if we should validate the request, but not change the configurations.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AlterConfigsRequestData(Readable readable, short version) {
+        this.resources = new AlterConfigsResourceSet(0);
+        read(readable, version);
+    }
+    
+    public AlterConfigsRequestData(Struct struct, short version) {
+        this.resources = new AlterConfigsResourceSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public AlterConfigsRequestData() {
+        this.resources = new AlterConfigsResourceSet(0);
+        this.validateOnly = false;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 33;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.resources.clear(0);
+            } else {
+                this.resources.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.resources.add(new AlterConfigsResource(readable, version));
+                }
+            }
+        }
+        this.validateOnly = readable.readByte() != 0;
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(resources.size());
+        for (AlterConfigsResource element : resources) {
+            element.write(writable, version);
+        }
+        writable.writeByte(validateOnly ? (byte) 1 : (byte) 0);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("resources");
+            this.resources = new AlterConfigsResourceSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.resources.add(new AlterConfigsResource((Struct) nestedObject, version));
+            }
+        }
+        this.validateOnly = struct.getBoolean("validate_only");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[resources.size()];
+            int i = 0;
+            for (AlterConfigsResource element : this.resources) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("resources", (Object[]) nestedObjects);
+        }
+        struct.set("validate_only", this.validateOnly);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (AlterConfigsResource element : resources) {
+            size += element.size(version);
+        }
+        size += 1;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AlterConfigsRequestData)) return false;
+        AlterConfigsRequestData other = (AlterConfigsRequestData) obj;
+        if (this.resources == null) {
+            if (other.resources != null) return false;
+        } else {
+            if (!this.resources.equals(other.resources)) return false;
+        }
+        if (validateOnly != other.validateOnly) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (resources == null ? 0 : resources.hashCode());
+        hashCode = 31 * hashCode + (validateOnly ? 1231 : 1237);
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AlterConfigsRequestData("
+            + "resources=" + MessageUtil.deepToString(resources.iterator())
+            + ", validateOnly=" + (validateOnly ? "true" : "false")
+            + ")";
+    }
+    
+    public AlterConfigsResourceSet resources() {
+        return this.resources;
+    }
+    
+    public boolean validateOnly() {
+        return this.validateOnly;
+    }
+    
+    public AlterConfigsRequestData setResources(AlterConfigsResourceSet v) {
+        this.resources = v;
+        return this;
+    }
+    
+    public AlterConfigsRequestData setValidateOnly(boolean v) {
+        this.validateOnly = v;
+        return this;
+    }
+    
+    static public class AlterConfigsResource implements Message, ImplicitLinkedHashMultiSet.Element {
+        private byte resourceType;
+        private String resourceName;
+        private AlterableConfigSet configs;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("resource_type", Type.INT8, "The resource type."),
+                new Field("resource_name", Type.STRING, "The resource name."),
+                new Field("configs", new ArrayOf(AlterableConfig.SCHEMA_0), "The configurations.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterConfigsResource(Readable readable, short version) {
+            this.configs = new AlterableConfigSet(0);
+            read(readable, version);
+        }
+        
+        public AlterConfigsResource(Struct struct, short version) {
+            this.configs = new AlterableConfigSet(0);
+            fromStruct(struct, version);
+        }
+        
+        public AlterConfigsResource() {
+            this.resourceType = (byte) 0;
+            this.resourceName = "";
+            this.configs = new AlterableConfigSet(0);
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.resourceType = readable.readByte();
+            this.resourceName = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.configs.clear(0);
+                } else {
+                    this.configs.clear(arrayLength);
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.configs.add(new AlterableConfig(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeByte(resourceType);
+            writable.writeString(resourceName);
+            writable.writeInt(configs.size());
+            for (AlterableConfig element : configs) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.resourceType = struct.getByte("resource_type");
+            this.resourceName = struct.getString("resource_name");
+            {
+                Object[] nestedObjects = struct.getArray("configs");
+                this.configs = new AlterableConfigSet(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.configs.add(new AlterableConfig((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("resource_type", this.resourceType);
+            struct.set("resource_name", this.resourceName);
+            {
+                Struct[] nestedObjects = new Struct[configs.size()];
+                int i = 0;
+                for (AlterableConfig element : this.configs) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("configs", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 1;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(resourceName);
+            size += 4;
+            for (AlterableConfig element : configs) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterConfigsResource)) return false;
+            AlterConfigsResource other = (AlterConfigsResource) obj;
+            if (resourceType != other.resourceType) return false;
+            if (this.resourceName == null) {
+                if (other.resourceName != null) return false;
+            } else {
+                if (!this.resourceName.equals(other.resourceName)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + resourceType;
+            hashCode = 31 * hashCode + (resourceName == null ? 0 : resourceName.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterConfigsResource("
+                + "resourceType=" + resourceType
+                + ", resourceName='" + resourceName + "'"
+                + ", configs=" + MessageUtil.deepToString(configs.iterator())
+                + ")";
+        }
+        
+        public byte resourceType() {
+            return this.resourceType;
+        }
+        
+        public String resourceName() {
+            return this.resourceName;
+        }
+        
+        public AlterableConfigSet configs() {
+            return this.configs;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AlterConfigsResource setResourceType(byte v) {
+            this.resourceType = v;
+            return this;
+        }
+        
+        public AlterConfigsResource setResourceName(String v) {
+            this.resourceName = v;
+            return this;
+        }
+        
+        public AlterConfigsResource setConfigs(AlterableConfigSet v) {
+            this.configs = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    static public class AlterableConfig implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private String value;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The configuration key name."),
+                new Field("value", Type.NULLABLE_STRING, "The value to set for the configuration key.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterableConfig(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public AlterableConfig(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public AlterableConfig() {
+            this.name = "";
+            this.value = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.value = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeNullableString(value);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.value = struct.getString("value");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("value", this.value);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 2;
+            if (value != null) {
+                size += MessageUtil.serializedUtf8Length(value);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterableConfig)) return false;
+            AlterableConfig other = (AlterableConfig) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterableConfig("
+                + "name='" + name + "'"
+                + ", value='" + value + "'"
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public String value() {
+            return this.value;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AlterableConfig setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public AlterableConfig setValue(String v) {
+            this.value = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class AlterableConfigSet extends ImplicitLinkedHashMultiSet<AlterableConfig> {
+        public AlterableConfigSet() {
+            super();
+        }
+        
+        public AlterableConfigSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AlterableConfigSet(Iterator<AlterableConfig> iterator) {
+            super(iterator);
+        }
+        
+        public AlterableConfig find(String name) {
+            AlterableConfig key = new AlterableConfig();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<AlterableConfig> findAll(String name) {
+            AlterableConfig key = new AlterableConfig();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+    
+    public static class AlterConfigsResourceSet extends ImplicitLinkedHashMultiSet<AlterConfigsResource> {
+        public AlterConfigsResourceSet() {
+            super();
+        }
+        
+        public AlterConfigsResourceSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AlterConfigsResourceSet(Iterator<AlterConfigsResource> iterator) {
+            super(iterator);
+        }
+        
+        public AlterConfigsResource find(byte resourceType, String resourceName) {
+            AlterConfigsResource key = new AlterConfigsResource();
+            key.setResourceType(resourceType);
+            key.setResourceName(resourceName);
+            return find(key);
+        }
+        
+        public List<AlterConfigsResource> findAll(byte resourceType, String resourceName) {
+            AlterConfigsResource key = new AlterConfigsResource();
+            key.setResourceType(resourceType);
+            key.setResourceName(resourceName);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsResponseData.java
new file mode 100644
index 0000000..39fb3cf
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AlterConfigsResponseData.java
@@ -0,0 +1,363 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class AlterConfigsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private List<AlterConfigsResourceResponse> resources;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "Duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("resources", new ArrayOf(AlterConfigsResourceResponse.SCHEMA_0), "The responses for each resource.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AlterConfigsResponseData(Readable readable, short version) {
+        this.resources = new ArrayList<AlterConfigsResourceResponse>();
+        read(readable, version);
+    }
+    
+    public AlterConfigsResponseData(Struct struct, short version) {
+        this.resources = new ArrayList<AlterConfigsResourceResponse>();
+        fromStruct(struct, version);
+    }
+    
+    public AlterConfigsResponseData() {
+        this.throttleTimeMs = 0;
+        this.resources = new ArrayList<AlterConfigsResourceResponse>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 33;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.resources.clear();
+            } else {
+                this.resources.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.resources.add(new AlterConfigsResourceResponse(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(resources.size());
+        for (AlterConfigsResourceResponse element : resources) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("resources");
+            this.resources = new ArrayList<AlterConfigsResourceResponse>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.resources.add(new AlterConfigsResourceResponse((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[resources.size()];
+            int i = 0;
+            for (AlterConfigsResourceResponse element : this.resources) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("resources", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (AlterConfigsResourceResponse element : resources) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AlterConfigsResponseData)) return false;
+        AlterConfigsResponseData other = (AlterConfigsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.resources == null) {
+            if (other.resources != null) return false;
+        } else {
+            if (!this.resources.equals(other.resources)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (resources == null ? 0 : resources.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AlterConfigsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", resources=" + MessageUtil.deepToString(resources.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public List<AlterConfigsResourceResponse> resources() {
+        return this.resources;
+    }
+    
+    public AlterConfigsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public AlterConfigsResponseData setResources(List<AlterConfigsResourceResponse> v) {
+        this.resources = v;
+        return this;
+    }
+    
+    static public class AlterConfigsResourceResponse implements Message {
+        private short errorCode;
+        private String errorMessage;
+        private byte resourceType;
+        private String resourceName;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The resource error code."),
+                new Field("error_message", Type.NULLABLE_STRING, "The resource error message, or null if there was no error."),
+                new Field("resource_type", Type.INT8, "The resource type."),
+                new Field("resource_name", Type.STRING, "The resource name.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterConfigsResourceResponse(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public AlterConfigsResourceResponse(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public AlterConfigsResourceResponse() {
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+            this.resourceType = (byte) 0;
+            this.resourceName = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.errorCode = readable.readShort();
+            this.errorMessage = readable.readNullableString();
+            this.resourceType = readable.readByte();
+            this.resourceName = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeShort(errorCode);
+            writable.writeNullableString(errorMessage);
+            writable.writeByte(resourceType);
+            writable.writeString(resourceName);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.errorCode = struct.getShort("error_code");
+            this.errorMessage = struct.getString("error_message");
+            this.resourceType = struct.getByte("resource_type");
+            this.resourceName = struct.getString("resource_name");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("error_code", this.errorCode);
+            struct.set("error_message", this.errorMessage);
+            struct.set("resource_type", this.resourceType);
+            struct.set("resource_name", this.resourceName);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += 2;
+            if (errorMessage != null) {
+                size += MessageUtil.serializedUtf8Length(errorMessage);
+            }
+            size += 1;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(resourceName);
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterConfigsResourceResponse)) return false;
+            AlterConfigsResourceResponse other = (AlterConfigsResourceResponse) obj;
+            if (errorCode != other.errorCode) return false;
+            if (this.errorMessage == null) {
+                if (other.errorMessage != null) return false;
+            } else {
+                if (!this.errorMessage.equals(other.errorMessage)) return false;
+            }
+            if (resourceType != other.resourceType) return false;
+            if (this.resourceName == null) {
+                if (other.resourceName != null) return false;
+            } else {
+                if (!this.resourceName.equals(other.resourceName)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + errorCode;
+            hashCode = 31 * hashCode + (errorMessage == null ? 0 : errorMessage.hashCode());
+            hashCode = 31 * hashCode + resourceType;
+            hashCode = 31 * hashCode + (resourceName == null ? 0 : resourceName.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterConfigsResourceResponse("
+                + "errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ", resourceType=" + resourceType
+                + ", resourceName='" + resourceName + "'"
+                + ")";
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        public byte resourceType() {
+            return this.resourceType;
+        }
+        
+        public String resourceName() {
+            return this.resourceName;
+        }
+        
+        public AlterConfigsResourceResponse setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public AlterConfigsResourceResponse setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+        
+        public AlterConfigsResourceResponse setResourceType(byte v) {
+            this.resourceType = v;
+            return this;
+        }
+        
+        public AlterConfigsResourceResponse setResourceName(String v) {
+            this.resourceName = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsRequestData.java
new file mode 100644
index 0000000..d95c741
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsRequestData.java
@@ -0,0 +1,576 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class AlterReplicaLogDirsRequestData implements ApiMessage {
+    private AlterReplicaLogDirSet dirs;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("dirs", new ArrayOf(AlterReplicaLogDir.SCHEMA_0), "The alterations to make for each directory.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AlterReplicaLogDirsRequestData(Readable readable, short version) {
+        this.dirs = new AlterReplicaLogDirSet(0);
+        read(readable, version);
+    }
+    
+    public AlterReplicaLogDirsRequestData(Struct struct, short version) {
+        this.dirs = new AlterReplicaLogDirSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public AlterReplicaLogDirsRequestData() {
+        this.dirs = new AlterReplicaLogDirSet(0);
+    }
+    
+    @Override
+    public short apiKey() {
+        return 34;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.dirs.clear(0);
+            } else {
+                this.dirs.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.dirs.add(new AlterReplicaLogDir(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(dirs.size());
+        for (AlterReplicaLogDir element : dirs) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("dirs");
+            this.dirs = new AlterReplicaLogDirSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.dirs.add(new AlterReplicaLogDir((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[dirs.size()];
+            int i = 0;
+            for (AlterReplicaLogDir element : this.dirs) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("dirs", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (AlterReplicaLogDir element : dirs) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AlterReplicaLogDirsRequestData)) return false;
+        AlterReplicaLogDirsRequestData other = (AlterReplicaLogDirsRequestData) obj;
+        if (this.dirs == null) {
+            if (other.dirs != null) return false;
+        } else {
+            if (!this.dirs.equals(other.dirs)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (dirs == null ? 0 : dirs.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AlterReplicaLogDirsRequestData("
+            + "dirs=" + MessageUtil.deepToString(dirs.iterator())
+            + ")";
+    }
+    
+    public AlterReplicaLogDirSet dirs() {
+        return this.dirs;
+    }
+    
+    public AlterReplicaLogDirsRequestData setDirs(AlterReplicaLogDirSet v) {
+        this.dirs = v;
+        return this;
+    }
+    
+    static public class AlterReplicaLogDir implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String path;
+        private AlterReplicaLogDirTopicSet topics;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("path", Type.STRING, "The absolute directory path."),
+                new Field("topics", new ArrayOf(AlterReplicaLogDirTopic.SCHEMA_0), "The topics to add to the directory.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterReplicaLogDir(Readable readable, short version) {
+            this.topics = new AlterReplicaLogDirTopicSet(0);
+            read(readable, version);
+        }
+        
+        public AlterReplicaLogDir(Struct struct, short version) {
+            this.topics = new AlterReplicaLogDirTopicSet(0);
+            fromStruct(struct, version);
+        }
+        
+        public AlterReplicaLogDir() {
+            this.path = "";
+            this.topics = new AlterReplicaLogDirTopicSet(0);
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.path = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.topics.clear(0);
+                } else {
+                    this.topics.clear(arrayLength);
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.topics.add(new AlterReplicaLogDirTopic(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(path);
+            writable.writeInt(topics.size());
+            for (AlterReplicaLogDirTopic element : topics) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.path = struct.getString("path");
+            {
+                Object[] nestedObjects = struct.getArray("topics");
+                this.topics = new AlterReplicaLogDirTopicSet(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.topics.add(new AlterReplicaLogDirTopic((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("path", this.path);
+            {
+                Struct[] nestedObjects = new Struct[topics.size()];
+                int i = 0;
+                for (AlterReplicaLogDirTopic element : this.topics) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("topics", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(path);
+            size += 4;
+            for (AlterReplicaLogDirTopic element : topics) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterReplicaLogDir)) return false;
+            AlterReplicaLogDir other = (AlterReplicaLogDir) obj;
+            if (this.path == null) {
+                if (other.path != null) return false;
+            } else {
+                if (!this.path.equals(other.path)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (path == null ? 0 : path.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterReplicaLogDir("
+                + "path='" + path + "'"
+                + ", topics=" + MessageUtil.deepToString(topics.iterator())
+                + ")";
+        }
+        
+        public String path() {
+            return this.path;
+        }
+        
+        public AlterReplicaLogDirTopicSet topics() {
+            return this.topics;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AlterReplicaLogDir setPath(String v) {
+            this.path = v;
+            return this;
+        }
+        
+        public AlterReplicaLogDir setTopics(AlterReplicaLogDirTopicSet v) {
+            this.topics = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    static public class AlterReplicaLogDirTopic implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private List<Integer> partitions;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("partitions", new ArrayOf(Type.INT32), "The partition indexes.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterReplicaLogDirTopic(Readable readable, short version) {
+            this.partitions = new ArrayList<Integer>();
+            read(readable, version);
+        }
+        
+        public AlterReplicaLogDirTopic(Struct struct, short version) {
+            this.partitions = new ArrayList<Integer>();
+            fromStruct(struct, version);
+        }
+        
+        public AlterReplicaLogDirTopic() {
+            this.name = "";
+            this.partitions = new ArrayList<Integer>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.partitions.clear();
+                } else {
+                    this.partitions.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.partitions.add(readable.readInt());
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeInt(partitions.size());
+            for (Integer element : partitions) {
+                writable.writeInt(element);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            {
+                Object[] nestedObjects = struct.getArray("partitions");
+                this.partitions = new ArrayList<Integer>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.partitions.add((Integer) nestedObject);
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            {
+                Integer[] nestedObjects = new Integer[partitions.size()];
+                int i = 0;
+                for (Integer element : this.partitions) {
+                    nestedObjects[i++] = element;
+                }
+                struct.set("partitions", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 4;
+            size += partitions.size() * 4;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterReplicaLogDirTopic)) return false;
+            AlterReplicaLogDirTopic other = (AlterReplicaLogDirTopic) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterReplicaLogDirTopic("
+                + "name='" + name + "'"
+                + ", partitions=" + MessageUtil.deepToString(partitions.iterator())
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public List<Integer> partitions() {
+            return this.partitions;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public AlterReplicaLogDirTopic setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public AlterReplicaLogDirTopic setPartitions(List<Integer> v) {
+            this.partitions = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class AlterReplicaLogDirTopicSet extends ImplicitLinkedHashMultiSet<AlterReplicaLogDirTopic> {
+        public AlterReplicaLogDirTopicSet() {
+            super();
+        }
+        
+        public AlterReplicaLogDirTopicSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AlterReplicaLogDirTopicSet(Iterator<AlterReplicaLogDirTopic> iterator) {
+            super(iterator);
+        }
+        
+        public AlterReplicaLogDirTopic find(String name) {
+            AlterReplicaLogDirTopic key = new AlterReplicaLogDirTopic();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<AlterReplicaLogDirTopic> findAll(String name) {
+            AlterReplicaLogDirTopic key = new AlterReplicaLogDirTopic();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+    
+    public static class AlterReplicaLogDirSet extends ImplicitLinkedHashMultiSet<AlterReplicaLogDir> {
+        public AlterReplicaLogDirSet() {
+            super();
+        }
+        
+        public AlterReplicaLogDirSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public AlterReplicaLogDirSet(Iterator<AlterReplicaLogDir> iterator) {
+            super(iterator);
+        }
+        
+        public AlterReplicaLogDir find(String path) {
+            AlterReplicaLogDir key = new AlterReplicaLogDir();
+            key.setPath(path);
+            return find(key);
+        }
+        
+        public List<AlterReplicaLogDir> findAll(String path) {
+            AlterReplicaLogDir key = new AlterReplicaLogDir();
+            key.setPath(path);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsResponseData.java
new file mode 100644
index 0000000..45a2c18
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/AlterReplicaLogDirsResponseData.java
@@ -0,0 +1,470 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class AlterReplicaLogDirsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private List<AlterReplicaLogDirTopicResult> results;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "Duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("results", new ArrayOf(AlterReplicaLogDirTopicResult.SCHEMA_0), "The results for each topic.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public AlterReplicaLogDirsResponseData(Readable readable, short version) {
+        this.results = new ArrayList<AlterReplicaLogDirTopicResult>();
+        read(readable, version);
+    }
+    
+    public AlterReplicaLogDirsResponseData(Struct struct, short version) {
+        this.results = new ArrayList<AlterReplicaLogDirTopicResult>();
+        fromStruct(struct, version);
+    }
+    
+    public AlterReplicaLogDirsResponseData() {
+        this.throttleTimeMs = 0;
+        this.results = new ArrayList<AlterReplicaLogDirTopicResult>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 34;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.results.clear();
+            } else {
+                this.results.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.results.add(new AlterReplicaLogDirTopicResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(results.size());
+        for (AlterReplicaLogDirTopicResult element : results) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("results");
+            this.results = new ArrayList<AlterReplicaLogDirTopicResult>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.results.add(new AlterReplicaLogDirTopicResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[results.size()];
+            int i = 0;
+            for (AlterReplicaLogDirTopicResult element : this.results) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("results", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (AlterReplicaLogDirTopicResult element : results) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AlterReplicaLogDirsResponseData)) return false;
+        AlterReplicaLogDirsResponseData other = (AlterReplicaLogDirsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.results == null) {
+            if (other.results != null) return false;
+        } else {
+            if (!this.results.equals(other.results)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (results == null ? 0 : results.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "AlterReplicaLogDirsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", results=" + MessageUtil.deepToString(results.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public List<AlterReplicaLogDirTopicResult> results() {
+        return this.results;
+    }
+    
+    public AlterReplicaLogDirsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public AlterReplicaLogDirsResponseData setResults(List<AlterReplicaLogDirTopicResult> v) {
+        this.results = v;
+        return this;
+    }
+    
+    static public class AlterReplicaLogDirTopicResult implements Message {
+        private String topicName;
+        private List<AlterReplicaLogDirPartitionResult> partitions;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("topic_name", Type.STRING, "The name of the topic."),
+                new Field("partitions", new ArrayOf(AlterReplicaLogDirPartitionResult.SCHEMA_0), "The results for each partition.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterReplicaLogDirTopicResult(Readable readable, short version) {
+            this.partitions = new ArrayList<AlterReplicaLogDirPartitionResult>();
+            read(readable, version);
+        }
+        
+        public AlterReplicaLogDirTopicResult(Struct struct, short version) {
+            this.partitions = new ArrayList<AlterReplicaLogDirPartitionResult>();
+            fromStruct(struct, version);
+        }
+        
+        public AlterReplicaLogDirTopicResult() {
+            this.topicName = "";
+            this.partitions = new ArrayList<AlterReplicaLogDirPartitionResult>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.topicName = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.partitions.clear();
+                } else {
+                    this.partitions.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.partitions.add(new AlterReplicaLogDirPartitionResult(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(topicName);
+            writable.writeInt(partitions.size());
+            for (AlterReplicaLogDirPartitionResult element : partitions) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.topicName = struct.getString("topic_name");
+            {
+                Object[] nestedObjects = struct.getArray("partitions");
+                this.partitions = new ArrayList<AlterReplicaLogDirPartitionResult>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.partitions.add(new AlterReplicaLogDirPartitionResult((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("topic_name", this.topicName);
+            {
+                Struct[] nestedObjects = new Struct[partitions.size()];
+                int i = 0;
+                for (AlterReplicaLogDirPartitionResult element : this.partitions) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("partitions", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(topicName);
+            size += 4;
+            for (AlterReplicaLogDirPartitionResult element : partitions) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterReplicaLogDirTopicResult)) return false;
+            AlterReplicaLogDirTopicResult other = (AlterReplicaLogDirTopicResult) obj;
+            if (this.topicName == null) {
+                if (other.topicName != null) return false;
+            } else {
+                if (!this.topicName.equals(other.topicName)) return false;
+            }
+            if (this.partitions == null) {
+                if (other.partitions != null) return false;
+            } else {
+                if (!this.partitions.equals(other.partitions)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (topicName == null ? 0 : topicName.hashCode());
+            hashCode = 31 * hashCode + (partitions == null ? 0 : partitions.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterReplicaLogDirTopicResult("
+                + "topicName='" + topicName + "'"
+                + ", partitions=" + MessageUtil.deepToString(partitions.iterator())
+                + ")";
+        }
+        
+        public String topicName() {
+            return this.topicName;
+        }
+        
+        public List<AlterReplicaLogDirPartitionResult> partitions() {
+            return this.partitions;
+        }
+        
+        public AlterReplicaLogDirTopicResult setTopicName(String v) {
+            this.topicName = v;
+            return this;
+        }
+        
+        public AlterReplicaLogDirTopicResult setPartitions(List<AlterReplicaLogDirPartitionResult> v) {
+            this.partitions = v;
+            return this;
+        }
+    }
+    
+    static public class AlterReplicaLogDirPartitionResult implements Message {
+        private int partitionIndex;
+        private short errorCode;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("partition_index", Type.INT32, "The partition index."),
+                new Field("error_code", Type.INT16, "The error code, or 0 if there was no error.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public AlterReplicaLogDirPartitionResult(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public AlterReplicaLogDirPartitionResult(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public AlterReplicaLogDirPartitionResult() {
+            this.partitionIndex = 0;
+            this.errorCode = (short) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.partitionIndex = readable.readInt();
+            this.errorCode = readable.readShort();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeInt(partitionIndex);
+            writable.writeShort(errorCode);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.partitionIndex = struct.getInt("partition_index");
+            this.errorCode = struct.getShort("error_code");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("partition_index", this.partitionIndex);
+            struct.set("error_code", this.errorCode);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 4;
+            size += 2;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AlterReplicaLogDirPartitionResult)) return false;
+            AlterReplicaLogDirPartitionResult other = (AlterReplicaLogDirPartitionResult) obj;
+            if (partitionIndex != other.partitionIndex) return false;
+            if (errorCode != other.errorCode) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + partitionIndex;
+            hashCode = 31 * hashCode + errorCode;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "AlterReplicaLogDirPartitionResult("
+                + "partitionIndex=" + partitionIndex
+                + ", errorCode=" + errorCode
+                + ")";
+        }
+        
+        public int partitionIndex() {
+            return this.partitionIndex;
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public AlterReplicaLogDirPartitionResult setPartitionIndex(int v) {
+            this.partitionIndex = v;
+            return this;
+        }
+        
+        public AlterReplicaLogDirPartitionResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/ApiMessageFactory.java b/clients/src/generated/java/org/apache/kafka/common/message/ApiMessageFactory.java
new file mode 100644
index 0000000..f6177e0
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/ApiMessageFactory.java
@@ -0,0 +1,398 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import org.apache.kafka.common.errors.UnsupportedVersionException;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.types.Schema;
+
+public final class ApiMessageFactory {
+    public static Message newRequest(short apiKey) {
+        switch (apiKey) {
+            case 0:
+                return new ProduceRequestData();
+            case 1:
+                return new FetchRequestData();
+            case 2:
+                return new ListOffsetRequestData();
+            case 3:
+                return new MetadataRequestData();
+            case 4:
+                return new LeaderAndIsrRequestData();
+            case 5:
+                return new StopReplicaRequestData();
+            case 6:
+                return new UpdateMetadataRequestData();
+            case 7:
+                return new ControlledShutdownRequestData();
+            case 8:
+                return new OffsetCommitRequestData();
+            case 9:
+                return new OffsetFetchRequestData();
+            case 10:
+                return new FindCoordinatorRequestData();
+            case 11:
+                return new JoinGroupRequestData();
+            case 12:
+                return new HeartbeatRequestData();
+            case 13:
+                return new LeaveGroupRequestData();
+            case 14:
+                return new SyncGroupRequestData();
+            case 15:
+                return new DescribeGroupsRequestData();
+            case 16:
+                return new ListGroupsRequestData();
+            case 17:
+                return new SaslHandshakeRequestData();
+            case 18:
+                return new ApiVersionsRequestData();
+            case 19:
+                return new CreateTopicsRequestData();
+            case 20:
+                return new DeleteTopicsRequestData();
+            case 21:
+                return new DeleteRecordsRequestData();
+            case 22:
+                return new InitProducerIdRequestData();
+            case 23:
+                return new OffsetForLeaderEpochRequestData();
+            case 24:
+                return new AddPartitionsToTxnRequestData();
+            case 25:
+                return new AddOffsetsToTxnRequestData();
+            case 26:
+                return new EndTxnRequestData();
+            case 27:
+                return new WriteTxnMarkersRequestData();
+            case 28:
+                return new TxnOffsetCommitRequestData();
+            case 29:
+                return new DescribeAclsRequestData();
+            case 30:
+                return new CreateAclsRequestData();
+            case 31:
+                return new DeleteAclsRequestData();
+            case 32:
+                return new DescribeConfigsRequestData();
+            case 33:
+                return new AlterConfigsRequestData();
+            case 34:
+                return new AlterReplicaLogDirsRequestData();
+            case 35:
+                return new DescribeLogDirsRequestData();
+            case 36:
+                return new SaslAuthenticateRequestData();
+            case 37:
+                return new CreatePartitionsRequestData();
+            case 38:
+                return new CreateDelegationTokenRequestData();
+            case 39:
+                return new RenewDelegationTokenRequestData();
+            case 40:
+                return new ExpireDelegationTokenRequestData();
+            case 41:
+                return new DescribeDelegationTokenRequestData();
+            case 42:
+                return new DeleteGroupsRequestData();
+            default:
+                throw new UnsupportedVersionException("Unsupported request API key " + apiKey);
+        }
+    }
+    
+    public static Message newResponse(short apiKey) {
+        switch (apiKey) {
+            case 0:
+                return new ProduceResponseData();
+            case 1:
+                return new FetchResponseData();
+            case 2:
+                return new ListOffsetResponseData();
+            case 3:
+                return new MetadataResponseData();
+            case 4:
+                return new LeaderAndIsrResponseData();
+            case 5:
+                return new StopReplicaResponseData();
+            case 6:
+                return new UpdateMetadataResponseData();
+            case 7:
+                return new ControlledShutdownResponseData();
+            case 8:
+                return new OffsetCommitResponseData();
+            case 9:
+                return new OffsetFetchResponseData();
+            case 10:
+                return new FindCoordinatorResponseData();
+            case 11:
+                return new JoinGroupResponseData();
+            case 12:
+                return new HeartbeatResponseData();
+            case 13:
+                return new LeaveGroupResponseData();
+            case 14:
+                return new SyncGroupResponseData();
+            case 15:
+                return new DescribeGroupsResponseData();
+            case 16:
+                return new ListGroupsResponseData();
+            case 17:
+                return new SaslHandshakeResponseData();
+            case 18:
+                return new ApiVersionsResponseData();
+            case 19:
+                return new CreateTopicsResponseData();
+            case 20:
+                return new DeleteTopicsResponseData();
+            case 21:
+                return new DeleteRecordsResponseData();
+            case 22:
+                return new InitProducerIdResponseData();
+            case 23:
+                return new OffsetForLeaderEpochResponseData();
+            case 24:
+                return new AddPartitionsToTxnResponseData();
+            case 25:
+                return new AddOffsetsToTxnResponseData();
+            case 26:
+                return new EndTxnResponseData();
+            case 27:
+                return new WriteTxnMarkersResponseData();
+            case 28:
+                return new TxnOffsetCommitResponseData();
+            case 29:
+                return new DescribeAclsResponseData();
+            case 30:
+                return new CreateAclsResponseData();
+            case 31:
+                return new DeleteAclsResponseData();
+            case 32:
+                return new DescribeConfigsResponseData();
+            case 33:
+                return new AlterConfigsResponseData();
+            case 34:
+                return new AlterReplicaLogDirsResponseData();
+            case 35:
+                return new DescribeLogDirsResponseData();
+            case 36:
+                return new SaslAuthenticateResponseData();
+            case 37:
+                return new CreatePartitionsResponseData();
+            case 38:
+                return new CreateDelegationTokenResponseData();
+            case 39:
+                return new RenewDelegationTokenResponseData();
+            case 40:
+                return new ExpireDelegationTokenResponseData();
+            case 41:
+                return new DescribeDelegationTokenResponseData();
+            case 42:
+                return new DeleteGroupsResponseData();
+            default:
+                throw new UnsupportedVersionException("Unsupported response API key " + apiKey);
+        }
+    }
+    
+    public static Schema[] requestSchemas(short apiKey) {
+        switch (apiKey) {
+            case 0:
+                return ProduceRequestData.SCHEMAS;
+            case 1:
+                return FetchRequestData.SCHEMAS;
+            case 2:
+                return ListOffsetRequestData.SCHEMAS;
+            case 3:
+                return MetadataRequestData.SCHEMAS;
+            case 4:
+                return LeaderAndIsrRequestData.SCHEMAS;
+            case 5:
+                return StopReplicaRequestData.SCHEMAS;
+            case 6:
+                return UpdateMetadataRequestData.SCHEMAS;
+            case 7:
+                return ControlledShutdownRequestData.SCHEMAS;
+            case 8:
+                return OffsetCommitRequestData.SCHEMAS;
+            case 9:
+                return OffsetFetchRequestData.SCHEMAS;
+            case 10:
+                return FindCoordinatorRequestData.SCHEMAS;
+            case 11:
+                return JoinGroupRequestData.SCHEMAS;
+            case 12:
+                return HeartbeatRequestData.SCHEMAS;
+            case 13:
+                return LeaveGroupRequestData.SCHEMAS;
+            case 14:
+                return SyncGroupRequestData.SCHEMAS;
+            case 15:
+                return DescribeGroupsRequestData.SCHEMAS;
+            case 16:
+                return ListGroupsRequestData.SCHEMAS;
+            case 17:
+                return SaslHandshakeRequestData.SCHEMAS;
+            case 18:
+                return ApiVersionsRequestData.SCHEMAS;
+            case 19:
+                return CreateTopicsRequestData.SCHEMAS;
+            case 20:
+                return DeleteTopicsRequestData.SCHEMAS;
+            case 21:
+                return DeleteRecordsRequestData.SCHEMAS;
+            case 22:
+                return InitProducerIdRequestData.SCHEMAS;
+            case 23:
+                return OffsetForLeaderEpochRequestData.SCHEMAS;
+            case 24:
+                return AddPartitionsToTxnRequestData.SCHEMAS;
+            case 25:
+                return AddOffsetsToTxnRequestData.SCHEMAS;
+            case 26:
+                return EndTxnRequestData.SCHEMAS;
+            case 27:
+                return WriteTxnMarkersRequestData.SCHEMAS;
+            case 28:
+                return TxnOffsetCommitRequestData.SCHEMAS;
+            case 29:
+                return DescribeAclsRequestData.SCHEMAS;
+            case 30:
+                return CreateAclsRequestData.SCHEMAS;
+            case 31:
+                return DeleteAclsRequestData.SCHEMAS;
+            case 32:
+                return DescribeConfigsRequestData.SCHEMAS;
+            case 33:
+                return AlterConfigsRequestData.SCHEMAS;
+            case 34:
+                return AlterReplicaLogDirsRequestData.SCHEMAS;
+            case 35:
+                return DescribeLogDirsRequestData.SCHEMAS;
+            case 36:
+                return SaslAuthenticateRequestData.SCHEMAS;
+            case 37:
+                return CreatePartitionsRequestData.SCHEMAS;
+            case 38:
+                return CreateDelegationTokenRequestData.SCHEMAS;
+            case 39:
+                return RenewDelegationTokenRequestData.SCHEMAS;
+            case 40:
+                return ExpireDelegationTokenRequestData.SCHEMAS;
+            case 41:
+                return DescribeDelegationTokenRequestData.SCHEMAS;
+            case 42:
+                return DeleteGroupsRequestData.SCHEMAS;
+            default:
+                throw new UnsupportedVersionException("Unsupported request API key " + apiKey);
+        }
+    }
+    
+    public static Schema[] responseSchemas(short apiKey) {
+        switch (apiKey) {
+            case 0:
+                return ProduceResponseData.SCHEMAS;
+            case 1:
+                return FetchResponseData.SCHEMAS;
+            case 2:
+                return ListOffsetResponseData.SCHEMAS;
+            case 3:
+                return MetadataResponseData.SCHEMAS;
+            case 4:
+                return LeaderAndIsrResponseData.SCHEMAS;
+            case 5:
+                return StopReplicaResponseData.SCHEMAS;
+            case 6:
+                return UpdateMetadataResponseData.SCHEMAS;
+            case 7:
+                return ControlledShutdownResponseData.SCHEMAS;
+            case 8:
+                return OffsetCommitResponseData.SCHEMAS;
+            case 9:
+                return OffsetFetchResponseData.SCHEMAS;
+            case 10:
+                return FindCoordinatorResponseData.SCHEMAS;
+            case 11:
+                return JoinGroupResponseData.SCHEMAS;
+            case 12:
+                return HeartbeatResponseData.SCHEMAS;
+            case 13:
+                return LeaveGroupResponseData.SCHEMAS;
+            case 14:
+                return SyncGroupResponseData.SCHEMAS;
+            case 15:
+                return DescribeGroupsResponseData.SCHEMAS;
+            case 16:
+                return ListGroupsResponseData.SCHEMAS;
+            case 17:
+                return SaslHandshakeResponseData.SCHEMAS;
+            case 18:
+                return ApiVersionsResponseData.SCHEMAS;
+            case 19:
+                return CreateTopicsResponseData.SCHEMAS;
+            case 20:
+                return DeleteTopicsResponseData.SCHEMAS;
+            case 21:
+                return DeleteRecordsResponseData.SCHEMAS;
+            case 22:
+                return InitProducerIdResponseData.SCHEMAS;
+            case 23:
+                return OffsetForLeaderEpochResponseData.SCHEMAS;
+            case 24:
+                return AddPartitionsToTxnResponseData.SCHEMAS;
+            case 25:
+                return AddOffsetsToTxnResponseData.SCHEMAS;
+            case 26:
+                return EndTxnResponseData.SCHEMAS;
+            case 27:
+                return WriteTxnMarkersResponseData.SCHEMAS;
+            case 28:
+                return TxnOffsetCommitResponseData.SCHEMAS;
+            case 29:
+                return DescribeAclsResponseData.SCHEMAS;
+            case 30:
+                return CreateAclsResponseData.SCHEMAS;
+            case 31:
+                return DeleteAclsResponseData.SCHEMAS;
+            case 32:
+                return DescribeConfigsResponseData.SCHEMAS;
+            case 33:
+                return AlterConfigsResponseData.SCHEMAS;
+            case 34:
+                return AlterReplicaLogDirsResponseData.SCHEMAS;
+            case 35:
+                return DescribeLogDirsResponseData.SCHEMAS;
+            case 36:
+                return SaslAuthenticateResponseData.SCHEMAS;
+            case 37:
+                return CreatePartitionsResponseData.SCHEMAS;
+            case 38:
+                return CreateDelegationTokenResponseData.SCHEMAS;
+            case 39:
+                return RenewDelegationTokenResponseData.SCHEMAS;
+            case 40:
+                return ExpireDelegationTokenResponseData.SCHEMAS;
+            case 41:
+                return DescribeDelegationTokenResponseData.SCHEMAS;
+            case 42:
+                return DeleteGroupsResponseData.SCHEMAS;
+            default:
+                throw new UnsupportedVersionException("Unsupported response API key " + apiKey);
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsRequestData.java
new file mode 100644
index 0000000..cd40482
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsRequestData.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+
+
+public class ApiVersionsRequestData implements ApiMessage {
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema SCHEMA_2 = SCHEMA_1;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2
+    };
+    
+    public ApiVersionsRequestData(Readable readable, short version) {
+        read(readable, version);
+    }
+    
+    public ApiVersionsRequestData(Struct struct, short version) {
+        fromStruct(struct, version);
+    }
+    
+    public ApiVersionsRequestData() {
+    }
+    
+    @Override
+    public short apiKey() {
+        return 18;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 2;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ApiVersionsRequestData)) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "ApiVersionsRequestData("
+            + ")";
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsResponseData.java
new file mode 100644
index 0000000..699971a
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/ApiVersionsResponseData.java
@@ -0,0 +1,421 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class ApiVersionsResponseData implements ApiMessage {
+    private short errorCode;
+    private ApiVersionsResponseKeySet apiKeys;
+    private int throttleTimeMs;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("error_code", Type.INT16, "The top-level error code."),
+            new Field("api_keys", new ArrayOf(ApiVersionsResponseKey.SCHEMA_0), "The APIs supported by the broker.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("error_code", Type.INT16, "The top-level error code."),
+            new Field("api_keys", new ArrayOf(ApiVersionsResponseKey.SCHEMA_0), "The APIs supported by the broker."),
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota.")
+        );
+    
+    public static final Schema SCHEMA_2 = SCHEMA_1;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2
+    };
+    
+    public ApiVersionsResponseData(Readable readable, short version) {
+        this.apiKeys = new ApiVersionsResponseKeySet(0);
+        read(readable, version);
+    }
+    
+    public ApiVersionsResponseData(Struct struct, short version) {
+        this.apiKeys = new ApiVersionsResponseKeySet(0);
+        fromStruct(struct, version);
+    }
+    
+    public ApiVersionsResponseData() {
+        this.errorCode = (short) 0;
+        this.apiKeys = new ApiVersionsResponseKeySet(0);
+        this.throttleTimeMs = 0;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 18;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 2;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.errorCode = readable.readShort();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.apiKeys.clear(0);
+            } else {
+                this.apiKeys.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.apiKeys.add(new ApiVersionsResponseKey(readable, version));
+                }
+            }
+        }
+        if (version >= 1) {
+            this.throttleTimeMs = readable.readInt();
+        } else {
+            this.throttleTimeMs = 0;
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeShort(errorCode);
+        writable.writeInt(apiKeys.size());
+        for (ApiVersionsResponseKey element : apiKeys) {
+            element.write(writable, version);
+        }
+        if (version >= 1) {
+            writable.writeInt(throttleTimeMs);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.errorCode = struct.getShort("error_code");
+        {
+            Object[] nestedObjects = struct.getArray("api_keys");
+            this.apiKeys = new ApiVersionsResponseKeySet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.apiKeys.add(new ApiVersionsResponseKey((Struct) nestedObject, version));
+            }
+        }
+        if (version >= 1) {
+            this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        } else {
+            this.throttleTimeMs = 0;
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("error_code", this.errorCode);
+        {
+            Struct[] nestedObjects = new Struct[apiKeys.size()];
+            int i = 0;
+            for (ApiVersionsResponseKey element : this.apiKeys) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("api_keys", (Object[]) nestedObjects);
+        }
+        if (version >= 1) {
+            struct.set("throttle_time_ms", this.throttleTimeMs);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 2;
+        size += 4;
+        for (ApiVersionsResponseKey element : apiKeys) {
+            size += element.size(version);
+        }
+        if (version >= 1) {
+            size += 4;
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ApiVersionsResponseData)) return false;
+        ApiVersionsResponseData other = (ApiVersionsResponseData) obj;
+        if (errorCode != other.errorCode) return false;
+        if (this.apiKeys == null) {
+            if (other.apiKeys != null) return false;
+        } else {
+            if (!this.apiKeys.equals(other.apiKeys)) return false;
+        }
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + errorCode;
+        hashCode = 31 * hashCode + (apiKeys == null ? 0 : apiKeys.hashCode());
+        hashCode = 31 * hashCode + throttleTimeMs;
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "ApiVersionsResponseData("
+            + "errorCode=" + errorCode
+            + ", apiKeys=" + MessageUtil.deepToString(apiKeys.iterator())
+            + ", throttleTimeMs=" + throttleTimeMs
+            + ")";
+    }
+    
+    public short errorCode() {
+        return this.errorCode;
+    }
+    
+    public ApiVersionsResponseKeySet apiKeys() {
+        return this.apiKeys;
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public ApiVersionsResponseData setErrorCode(short v) {
+        this.errorCode = v;
+        return this;
+    }
+    
+    public ApiVersionsResponseData setApiKeys(ApiVersionsResponseKeySet v) {
+        this.apiKeys = v;
+        return this;
+    }
+    
+    public ApiVersionsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    static public class ApiVersionsResponseKey implements Message, ImplicitLinkedHashMultiSet.Element {
+        private short index;
+        private short minVersion;
+        private short maxVersion;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("index", Type.INT16, "The API index."),
+                new Field("min_version", Type.INT16, "The minimum supported version, inclusive."),
+                new Field("max_version", Type.INT16, "The maximum supported version, inclusive.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2
+        };
+        
+        public ApiVersionsResponseKey(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public ApiVersionsResponseKey(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public ApiVersionsResponseKey() {
+            this.index = (short) 0;
+            this.minVersion = (short) 0;
+            this.maxVersion = (short) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 2;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.index = readable.readShort();
+            this.minVersion = readable.readShort();
+            this.maxVersion = readable.readShort();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeShort(index);
+            writable.writeShort(minVersion);
+            writable.writeShort(maxVersion);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.index = struct.getShort("index");
+            this.minVersion = struct.getShort("min_version");
+            this.maxVersion = struct.getShort("max_version");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("index", this.index);
+            struct.set("min_version", this.minVersion);
+            struct.set("max_version", this.maxVersion);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += 2;
+            size += 2;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ApiVersionsResponseKey)) return false;
+            ApiVersionsResponseKey other = (ApiVersionsResponseKey) obj;
+            if (index != other.index) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + index;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "ApiVersionsResponseKey("
+                + "index=" + index
+                + ", minVersion=" + minVersion
+                + ", maxVersion=" + maxVersion
+                + ")";
+        }
+        
+        public short index() {
+            return this.index;
+        }
+        
+        public short minVersion() {
+            return this.minVersion;
+        }
+        
+        public short maxVersion() {
+            return this.maxVersion;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public ApiVersionsResponseKey setIndex(short v) {
+            this.index = v;
+            return this;
+        }
+        
+        public ApiVersionsResponseKey setMinVersion(short v) {
+            this.minVersion = v;
+            return this;
+        }
+        
+        public ApiVersionsResponseKey setMaxVersion(short v) {
+            this.maxVersion = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class ApiVersionsResponseKeySet extends ImplicitLinkedHashMultiSet<ApiVersionsResponseKey> {
+        public ApiVersionsResponseKeySet() {
+            super();
+        }
+        
+        public ApiVersionsResponseKeySet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public ApiVersionsResponseKeySet(Iterator<ApiVersionsResponseKey> iterator) {
+            super(iterator);
+        }
+        
+        public ApiVersionsResponseKey find(short index) {
+            ApiVersionsResponseKey key = new ApiVersionsResponseKey();
+            key.setIndex(index);
+            return find(key);
+        }
+        
+        public List<ApiVersionsResponseKey> findAll(short index) {
+            ApiVersionsResponseKey key = new ApiVersionsResponseKey();
+            key.setIndex(index);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownRequestData.java
new file mode 100644
index 0000000..85688d5
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownRequestData.java
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class ControlledShutdownRequestData implements ApiMessage {
+    private int brokerId;
+    private long brokerEpoch;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("broker_id", Type.INT32, "The id of the broker for which controlled shutdown has been requested.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema SCHEMA_2 =
+        new Schema(
+            new Field("broker_id", Type.INT32, "The id of the broker for which controlled shutdown has been requested."),
+            new Field("broker_epoch", Type.INT64, "The broker epoch.")
+        );
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2
+    };
+    
+    public ControlledShutdownRequestData(Readable readable, short version) {
+        read(readable, version);
+    }
+    
+    public ControlledShutdownRequestData(Struct struct, short version) {
+        fromStruct(struct, version);
+    }
+    
+    public ControlledShutdownRequestData() {
+        this.brokerId = 0;
+        this.brokerEpoch = -1L;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 7;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 2;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.brokerId = readable.readInt();
+        if (version >= 2) {
+            this.brokerEpoch = readable.readLong();
+        } else {
+            this.brokerEpoch = -1L;
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(brokerId);
+        if (version >= 2) {
+            writable.writeLong(brokerEpoch);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.brokerId = struct.getInt("broker_id");
+        if (version >= 2) {
+            this.brokerEpoch = struct.getLong("broker_epoch");
+        } else {
+            this.brokerEpoch = -1L;
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("broker_id", this.brokerId);
+        if (version >= 2) {
+            struct.set("broker_epoch", this.brokerEpoch);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        if (version >= 2) {
+            size += 8;
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ControlledShutdownRequestData)) return false;
+        ControlledShutdownRequestData other = (ControlledShutdownRequestData) obj;
+        if (brokerId != other.brokerId) return false;
+        if (brokerEpoch != other.brokerEpoch) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + brokerId;
+        hashCode = 31 * hashCode + ((int) (brokerEpoch >> 32) ^ (int) brokerEpoch);
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "ControlledShutdownRequestData("
+            + "brokerId=" + brokerId
+            + ", brokerEpoch=" + brokerEpoch
+            + ")";
+    }
+    
+    public int brokerId() {
+        return this.brokerId;
+    }
+    
+    public long brokerEpoch() {
+        return this.brokerEpoch;
+    }
+    
+    public ControlledShutdownRequestData setBrokerId(int v) {
+        this.brokerId = v;
+        return this;
+    }
+    
+    public ControlledShutdownRequestData setBrokerEpoch(long v) {
+        this.brokerEpoch = v;
+        return this;
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownResponseData.java
new file mode 100644
index 0000000..9d95cf8
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/ControlledShutdownResponseData.java
@@ -0,0 +1,374 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class ControlledShutdownResponseData implements ApiMessage {
+    private short errorCode;
+    private RemainingPartitionSet remainingPartitions;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("error_code", Type.INT16, "The top-level error code."),
+            new Field("remaining_partitions", new ArrayOf(RemainingPartition.SCHEMA_0), "The partitions that the broker still leads.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema SCHEMA_2 = SCHEMA_1;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2
+    };
+    
+    public ControlledShutdownResponseData(Readable readable, short version) {
+        this.remainingPartitions = new RemainingPartitionSet(0);
+        read(readable, version);
+    }
+    
+    public ControlledShutdownResponseData(Struct struct, short version) {
+        this.remainingPartitions = new RemainingPartitionSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public ControlledShutdownResponseData() {
+        this.errorCode = (short) 0;
+        this.remainingPartitions = new RemainingPartitionSet(0);
+    }
+    
+    @Override
+    public short apiKey() {
+        return 7;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 2;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.errorCode = readable.readShort();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.remainingPartitions.clear(0);
+            } else {
+                this.remainingPartitions.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.remainingPartitions.add(new RemainingPartition(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeShort(errorCode);
+        writable.writeInt(remainingPartitions.size());
+        for (RemainingPartition element : remainingPartitions) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.errorCode = struct.getShort("error_code");
+        {
+            Object[] nestedObjects = struct.getArray("remaining_partitions");
+            this.remainingPartitions = new RemainingPartitionSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.remainingPartitions.add(new RemainingPartition((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("error_code", this.errorCode);
+        {
+            Struct[] nestedObjects = new Struct[remainingPartitions.size()];
+            int i = 0;
+            for (RemainingPartition element : this.remainingPartitions) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("remaining_partitions", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 2;
+        size += 4;
+        for (RemainingPartition element : remainingPartitions) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ControlledShutdownResponseData)) return false;
+        ControlledShutdownResponseData other = (ControlledShutdownResponseData) obj;
+        if (errorCode != other.errorCode) return false;
+        if (this.remainingPartitions == null) {
+            if (other.remainingPartitions != null) return false;
+        } else {
+            if (!this.remainingPartitions.equals(other.remainingPartitions)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + errorCode;
+        hashCode = 31 * hashCode + (remainingPartitions == null ? 0 : remainingPartitions.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "ControlledShutdownResponseData("
+            + "errorCode=" + errorCode
+            + ", remainingPartitions=" + MessageUtil.deepToString(remainingPartitions.iterator())
+            + ")";
+    }
+    
+    public short errorCode() {
+        return this.errorCode;
+    }
+    
+    public RemainingPartitionSet remainingPartitions() {
+        return this.remainingPartitions;
+    }
+    
+    public ControlledShutdownResponseData setErrorCode(short v) {
+        this.errorCode = v;
+        return this;
+    }
+    
+    public ControlledShutdownResponseData setRemainingPartitions(RemainingPartitionSet v) {
+        this.remainingPartitions = v;
+        return this;
+    }
+    
+    static public class RemainingPartition implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String topicName;
+        private int partitionIndex;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("topic_name", Type.STRING, "The name of the topic."),
+                new Field("partition_index", Type.INT32, "The index of the partition.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2
+        };
+        
+        public RemainingPartition(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public RemainingPartition(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public RemainingPartition() {
+            this.topicName = "";
+            this.partitionIndex = 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 2;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.topicName = readable.readNullableString();
+            this.partitionIndex = readable.readInt();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(topicName);
+            writable.writeInt(partitionIndex);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.topicName = struct.getString("topic_name");
+            this.partitionIndex = struct.getInt("partition_index");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("topic_name", this.topicName);
+            struct.set("partition_index", this.partitionIndex);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(topicName);
+            size += 4;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof RemainingPartition)) return false;
+            RemainingPartition other = (RemainingPartition) obj;
+            if (this.topicName == null) {
+                if (other.topicName != null) return false;
+            } else {
+                if (!this.topicName.equals(other.topicName)) return false;
+            }
+            if (partitionIndex != other.partitionIndex) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (topicName == null ? 0 : topicName.hashCode());
+            hashCode = 31 * hashCode + partitionIndex;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "RemainingPartition("
+                + "topicName='" + topicName + "'"
+                + ", partitionIndex=" + partitionIndex
+                + ")";
+        }
+        
+        public String topicName() {
+            return this.topicName;
+        }
+        
+        public int partitionIndex() {
+            return this.partitionIndex;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public RemainingPartition setTopicName(String v) {
+            this.topicName = v;
+            return this;
+        }
+        
+        public RemainingPartition setPartitionIndex(int v) {
+            this.partitionIndex = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class RemainingPartitionSet extends ImplicitLinkedHashMultiSet<RemainingPartition> {
+        public RemainingPartitionSet() {
+            super();
+        }
+        
+        public RemainingPartitionSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public RemainingPartitionSet(Iterator<RemainingPartition> iterator) {
+            super(iterator);
+        }
+        
+        public RemainingPartition find(String topicName, int partitionIndex) {
+            RemainingPartition key = new RemainingPartition();
+            key.setTopicName(topicName);
+            key.setPartitionIndex(partitionIndex);
+            return find(key);
+        }
+        
+        public List<RemainingPartition> findAll(String topicName, int partitionIndex) {
+            RemainingPartition key = new RemainingPartition();
+            key.setTopicName(topicName);
+            key.setPartitionIndex(partitionIndex);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsRequestData.java
new file mode 100644
index 0000000..df33c7e
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsRequestData.java
@@ -0,0 +1,436 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.errors.UnsupportedVersionException;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class CreateAclsRequestData implements ApiMessage {
+    private List<CreatableAcl> creations;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("creations", new ArrayOf(CreatableAcl.SCHEMA_0), "The ACLs that we want to create.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("creations", new ArrayOf(CreatableAcl.SCHEMA_1), "The ACLs that we want to create.")
+        );
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreateAclsRequestData(Readable readable, short version) {
+        this.creations = new ArrayList<CreatableAcl>();
+        read(readable, version);
+    }
+    
+    public CreateAclsRequestData(Struct struct, short version) {
+        this.creations = new ArrayList<CreatableAcl>();
+        fromStruct(struct, version);
+    }
+    
+    public CreateAclsRequestData() {
+        this.creations = new ArrayList<CreatableAcl>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 30;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.creations.clear();
+            } else {
+                this.creations.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.creations.add(new CreatableAcl(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(creations.size());
+        for (CreatableAcl element : creations) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("creations");
+            this.creations = new ArrayList<CreatableAcl>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.creations.add(new CreatableAcl((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[creations.size()];
+            int i = 0;
+            for (CreatableAcl element : this.creations) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("creations", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (CreatableAcl element : creations) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateAclsRequestData)) return false;
+        CreateAclsRequestData other = (CreateAclsRequestData) obj;
+        if (this.creations == null) {
+            if (other.creations != null) return false;
+        } else {
+            if (!this.creations.equals(other.creations)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (creations == null ? 0 : creations.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateAclsRequestData("
+            + "creations=" + MessageUtil.deepToString(creations.iterator())
+            + ")";
+    }
+    
+    public List<CreatableAcl> creations() {
+        return this.creations;
+    }
+    
+    public CreateAclsRequestData setCreations(List<CreatableAcl> v) {
+        this.creations = v;
+        return this;
+    }
+    
+    static public class CreatableAcl implements Message {
+        private byte resourceType;
+        private String resourceName;
+        private byte resourcePatternType;
+        private String principal;
+        private String host;
+        private byte operation;
+        private byte permissionType;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("resource_type", Type.INT8, "The type of the resource."),
+                new Field("resource_name", Type.STRING, "The resource name for the ACL."),
+                new Field("principal", Type.STRING, "The principal for the ACL."),
+                new Field("host", Type.STRING, "The host for the ACL."),
+                new Field("operation", Type.INT8, "The operation type for the ACL (read, write, etc.)."),
+                new Field("permission_type", Type.INT8, "The permission type for the ACL (allow, deny, etc.).")
+            );
+        
+        public static final Schema SCHEMA_1 =
+            new Schema(
+                new Field("resource_type", Type.INT8, "The type of the resource."),
+                new Field("resource_name", Type.STRING, "The resource name for the ACL."),
+                new Field("resource_pattern_type", Type.INT8, "The pattern type for the ACL."),
+                new Field("principal", Type.STRING, "The principal for the ACL."),
+                new Field("host", Type.STRING, "The host for the ACL."),
+                new Field("operation", Type.INT8, "The operation type for the ACL (read, write, etc.)."),
+                new Field("permission_type", Type.INT8, "The permission type for the ACL (allow, deny, etc.).")
+            );
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatableAcl(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreatableAcl(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreatableAcl() {
+            this.resourceType = (byte) 0;
+            this.resourceName = "";
+            this.resourcePatternType = (byte) 3;
+            this.principal = "";
+            this.host = "";
+            this.operation = (byte) 0;
+            this.permissionType = (byte) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.resourceType = readable.readByte();
+            this.resourceName = readable.readNullableString();
+            if (version >= 1) {
+                this.resourcePatternType = readable.readByte();
+            } else {
+                this.resourcePatternType = (byte) 3;
+            }
+            this.principal = readable.readNullableString();
+            this.host = readable.readNullableString();
+            this.operation = readable.readByte();
+            this.permissionType = readable.readByte();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeByte(resourceType);
+            writable.writeString(resourceName);
+            if (version >= 1) {
+                writable.writeByte(resourcePatternType);
+            }
+            writable.writeString(principal);
+            writable.writeString(host);
+            writable.writeByte(operation);
+            writable.writeByte(permissionType);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.resourceType = struct.getByte("resource_type");
+            this.resourceName = struct.getString("resource_name");
+            if (version >= 1) {
+                this.resourcePatternType = struct.getByte("resource_pattern_type");
+            } else {
+                this.resourcePatternType = (byte) 3;
+            }
+            this.principal = struct.getString("principal");
+            this.host = struct.getString("host");
+            this.operation = struct.getByte("operation");
+            this.permissionType = struct.getByte("permission_type");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("resource_type", this.resourceType);
+            struct.set("resource_name", this.resourceName);
+            if (version >= 1) {
+                struct.set("resource_pattern_type", this.resourcePatternType);
+            }
+            struct.set("principal", this.principal);
+            struct.set("host", this.host);
+            struct.set("operation", this.operation);
+            struct.set("permission_type", this.permissionType);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 1;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(resourceName);
+            if (version >= 1) {
+                size += 1;
+            } else {
+                if (resourcePatternType != (byte) 3) {
+                    throw new UnsupportedVersionException("Attempted to write a non-default resourcePatternType at version " + version);
+                }
+            }
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(principal);
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(host);
+            size += 1;
+            size += 1;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableAcl)) return false;
+            CreatableAcl other = (CreatableAcl) obj;
+            if (resourceType != other.resourceType) return false;
+            if (this.resourceName == null) {
+                if (other.resourceName != null) return false;
+            } else {
+                if (!this.resourceName.equals(other.resourceName)) return false;
+            }
+            if (resourcePatternType != other.resourcePatternType) return false;
+            if (this.principal == null) {
+                if (other.principal != null) return false;
+            } else {
+                if (!this.principal.equals(other.principal)) return false;
+            }
+            if (this.host == null) {
+                if (other.host != null) return false;
+            } else {
+                if (!this.host.equals(other.host)) return false;
+            }
+            if (operation != other.operation) return false;
+            if (permissionType != other.permissionType) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + resourceType;
+            hashCode = 31 * hashCode + (resourceName == null ? 0 : resourceName.hashCode());
+            hashCode = 31 * hashCode + resourcePatternType;
+            hashCode = 31 * hashCode + (principal == null ? 0 : principal.hashCode());
+            hashCode = 31 * hashCode + (host == null ? 0 : host.hashCode());
+            hashCode = 31 * hashCode + operation;
+            hashCode = 31 * hashCode + permissionType;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableAcl("
+                + "resourceType=" + resourceType
+                + ", resourceName='" + resourceName + "'"
+                + ", resourcePatternType=" + resourcePatternType
+                + ", principal='" + principal + "'"
+                + ", host='" + host + "'"
+                + ", operation=" + operation
+                + ", permissionType=" + permissionType
+                + ")";
+        }
+        
+        public byte resourceType() {
+            return this.resourceType;
+        }
+        
+        public String resourceName() {
+            return this.resourceName;
+        }
+        
+        public byte resourcePatternType() {
+            return this.resourcePatternType;
+        }
+        
+        public String principal() {
+            return this.principal;
+        }
+        
+        public String host() {
+            return this.host;
+        }
+        
+        public byte operation() {
+            return this.operation;
+        }
+        
+        public byte permissionType() {
+            return this.permissionType;
+        }
+        
+        public CreatableAcl setResourceType(byte v) {
+            this.resourceType = v;
+            return this;
+        }
+        
+        public CreatableAcl setResourceName(String v) {
+            this.resourceName = v;
+            return this;
+        }
+        
+        public CreatableAcl setResourcePatternType(byte v) {
+            this.resourcePatternType = v;
+            return this;
+        }
+        
+        public CreatableAcl setPrincipal(String v) {
+            this.principal = v;
+            return this;
+        }
+        
+        public CreatableAcl setHost(String v) {
+            this.host = v;
+            return this;
+        }
+        
+        public CreatableAcl setOperation(byte v) {
+            this.operation = v;
+            return this;
+        }
+        
+        public CreatableAcl setPermissionType(byte v) {
+            this.permissionType = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsResponseData.java
new file mode 100644
index 0000000..d856bf4
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateAclsResponseData.java
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class CreateAclsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private List<CreatableAclResult> results;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("results", new ArrayOf(CreatableAclResult.SCHEMA_0), "The results for each ACL creation.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreateAclsResponseData(Readable readable, short version) {
+        this.results = new ArrayList<CreatableAclResult>();
+        read(readable, version);
+    }
+    
+    public CreateAclsResponseData(Struct struct, short version) {
+        this.results = new ArrayList<CreatableAclResult>();
+        fromStruct(struct, version);
+    }
+    
+    public CreateAclsResponseData() {
+        this.throttleTimeMs = 0;
+        this.results = new ArrayList<CreatableAclResult>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 30;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.results.clear();
+            } else {
+                this.results.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.results.add(new CreatableAclResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(results.size());
+        for (CreatableAclResult element : results) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("results");
+            this.results = new ArrayList<CreatableAclResult>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.results.add(new CreatableAclResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[results.size()];
+            int i = 0;
+            for (CreatableAclResult element : this.results) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("results", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (CreatableAclResult element : results) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateAclsResponseData)) return false;
+        CreateAclsResponseData other = (CreateAclsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.results == null) {
+            if (other.results != null) return false;
+        } else {
+            if (!this.results.equals(other.results)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (results == null ? 0 : results.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateAclsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", results=" + MessageUtil.deepToString(results.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public List<CreatableAclResult> results() {
+        return this.results;
+    }
+    
+    public CreateAclsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public CreateAclsResponseData setResults(List<CreatableAclResult> v) {
+        this.results = v;
+        return this;
+    }
+    
+    static public class CreatableAclResult implements Message {
+        private short errorCode;
+        private String errorMessage;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The result error, or zero if there was no error."),
+                new Field("error_message", Type.NULLABLE_STRING, "The result message, or null if there was no error.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatableAclResult(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreatableAclResult(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreatableAclResult() {
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.errorCode = readable.readShort();
+            this.errorMessage = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeShort(errorCode);
+            writable.writeNullableString(errorMessage);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.errorCode = struct.getShort("error_code");
+            this.errorMessage = struct.getString("error_message");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("error_code", this.errorCode);
+            struct.set("error_message", this.errorMessage);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += 2;
+            if (errorMessage != null) {
+                size += MessageUtil.serializedUtf8Length(errorMessage);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableAclResult)) return false;
+            CreatableAclResult other = (CreatableAclResult) obj;
+            if (errorCode != other.errorCode) return false;
+            if (this.errorMessage == null) {
+                if (other.errorMessage != null) return false;
+            } else {
+                if (!this.errorMessage.equals(other.errorMessage)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + errorCode;
+            hashCode = 31 * hashCode + (errorMessage == null ? 0 : errorMessage.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableAclResult("
+                + "errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ")";
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        public CreatableAclResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public CreatableAclResult setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenRequestData.java
new file mode 100644
index 0000000..a5604cb
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenRequestData.java
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class CreateDelegationTokenRequestData implements ApiMessage {
+    private List<CreatableRenewers> renewers;
+    private long maxLifetimeMs;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("renewers", new ArrayOf(CreatableRenewers.SCHEMA_0), "A list of those who are allowed to renew this token before it expires."),
+            new Field("max_lifetime_ms", Type.INT64, "The maximum lifetime of the token in milliseconds, or -1 to use the server side default.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreateDelegationTokenRequestData(Readable readable, short version) {
+        this.renewers = new ArrayList<CreatableRenewers>();
+        read(readable, version);
+    }
+    
+    public CreateDelegationTokenRequestData(Struct struct, short version) {
+        this.renewers = new ArrayList<CreatableRenewers>();
+        fromStruct(struct, version);
+    }
+    
+    public CreateDelegationTokenRequestData() {
+        this.renewers = new ArrayList<CreatableRenewers>();
+        this.maxLifetimeMs = 0L;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 38;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.renewers.clear();
+            } else {
+                this.renewers.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.renewers.add(new CreatableRenewers(readable, version));
+                }
+            }
+        }
+        this.maxLifetimeMs = readable.readLong();
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(renewers.size());
+        for (CreatableRenewers element : renewers) {
+            element.write(writable, version);
+        }
+        writable.writeLong(maxLifetimeMs);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("renewers");
+            this.renewers = new ArrayList<CreatableRenewers>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.renewers.add(new CreatableRenewers((Struct) nestedObject, version));
+            }
+        }
+        this.maxLifetimeMs = struct.getLong("max_lifetime_ms");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[renewers.size()];
+            int i = 0;
+            for (CreatableRenewers element : this.renewers) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("renewers", (Object[]) nestedObjects);
+        }
+        struct.set("max_lifetime_ms", this.maxLifetimeMs);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (CreatableRenewers element : renewers) {
+            size += element.size(version);
+        }
+        size += 8;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateDelegationTokenRequestData)) return false;
+        CreateDelegationTokenRequestData other = (CreateDelegationTokenRequestData) obj;
+        if (this.renewers == null) {
+            if (other.renewers != null) return false;
+        } else {
+            if (!this.renewers.equals(other.renewers)) return false;
+        }
+        if (maxLifetimeMs != other.maxLifetimeMs) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (renewers == null ? 0 : renewers.hashCode());
+        hashCode = 31 * hashCode + ((int) (maxLifetimeMs >> 32) ^ (int) maxLifetimeMs);
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateDelegationTokenRequestData("
+            + "renewers=" + MessageUtil.deepToString(renewers.iterator())
+            + ", maxLifetimeMs=" + maxLifetimeMs
+            + ")";
+    }
+    
+    public List<CreatableRenewers> renewers() {
+        return this.renewers;
+    }
+    
+    public long maxLifetimeMs() {
+        return this.maxLifetimeMs;
+    }
+    
+    public CreateDelegationTokenRequestData setRenewers(List<CreatableRenewers> v) {
+        this.renewers = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenRequestData setMaxLifetimeMs(long v) {
+        this.maxLifetimeMs = v;
+        return this;
+    }
+    
+    static public class CreatableRenewers implements Message {
+        private String principalType;
+        private String principalName;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("principal_type", Type.STRING, "The type of the Kafka principal."),
+                new Field("principal_name", Type.STRING, "The name of the Kafka principal.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatableRenewers(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreatableRenewers(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreatableRenewers() {
+            this.principalType = "";
+            this.principalName = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.principalType = readable.readNullableString();
+            this.principalName = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(principalType);
+            writable.writeString(principalName);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.principalType = struct.getString("principal_type");
+            this.principalName = struct.getString("principal_name");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("principal_type", this.principalType);
+            struct.set("principal_name", this.principalName);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(principalType);
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(principalName);
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableRenewers)) return false;
+            CreatableRenewers other = (CreatableRenewers) obj;
+            if (this.principalType == null) {
+                if (other.principalType != null) return false;
+            } else {
+                if (!this.principalType.equals(other.principalType)) return false;
+            }
+            if (this.principalName == null) {
+                if (other.principalName != null) return false;
+            } else {
+                if (!this.principalName.equals(other.principalName)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (principalType == null ? 0 : principalType.hashCode());
+            hashCode = 31 * hashCode + (principalName == null ? 0 : principalName.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableRenewers("
+                + "principalType='" + principalType + "'"
+                + ", principalName='" + principalName + "'"
+                + ")";
+        }
+        
+        public String principalType() {
+            return this.principalType;
+        }
+        
+        public String principalName() {
+            return this.principalName;
+        }
+        
+        public CreatableRenewers setPrincipalType(String v) {
+            this.principalType = v;
+            return this;
+        }
+        
+        public CreatableRenewers setPrincipalName(String v) {
+            this.principalName = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenResponseData.java
new file mode 100644
index 0000000..31876de
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateDelegationTokenResponseData.java
@@ -0,0 +1,311 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Arrays;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.Bytes;
+
+
+public class CreateDelegationTokenResponseData implements ApiMessage {
+    private short errorCode;
+    private String principalType;
+    private String principalName;
+    private long issueTimestampMs;
+    private long expiryTimestampMs;
+    private long maxTimestampMs;
+    private String tokenId;
+    private byte[] hmac;
+    private int throttleTimeMs;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("error_code", Type.INT16, "The top-level error, or zero if there was no error."),
+            new Field("principal_type", Type.STRING, "The principal type of the token owner."),
+            new Field("principal_name", Type.STRING, "The name of the token owner."),
+            new Field("issue_timestamp_ms", Type.INT64, "When this token was generated."),
+            new Field("expiry_timestamp_ms", Type.INT64, "When this token expires."),
+            new Field("max_timestamp_ms", Type.INT64, "The maximum lifetime of this token."),
+            new Field("token_id", Type.STRING, "The token UUID."),
+            new Field("hmac", Type.BYTES, "HMAC of the delegation token."),
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreateDelegationTokenResponseData(Readable readable, short version) {
+        read(readable, version);
+    }
+    
+    public CreateDelegationTokenResponseData(Struct struct, short version) {
+        fromStruct(struct, version);
+    }
+    
+    public CreateDelegationTokenResponseData() {
+        this.errorCode = (short) 0;
+        this.principalType = "";
+        this.principalName = "";
+        this.issueTimestampMs = 0L;
+        this.expiryTimestampMs = 0L;
+        this.maxTimestampMs = 0L;
+        this.tokenId = "";
+        this.hmac = Bytes.EMPTY;
+        this.throttleTimeMs = 0;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 38;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.errorCode = readable.readShort();
+        this.principalType = readable.readNullableString();
+        this.principalName = readable.readNullableString();
+        this.issueTimestampMs = readable.readLong();
+        this.expiryTimestampMs = readable.readLong();
+        this.maxTimestampMs = readable.readLong();
+        this.tokenId = readable.readNullableString();
+        this.hmac = readable.readNullableBytes();
+        this.throttleTimeMs = readable.readInt();
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeShort(errorCode);
+        writable.writeString(principalType);
+        writable.writeString(principalName);
+        writable.writeLong(issueTimestampMs);
+        writable.writeLong(expiryTimestampMs);
+        writable.writeLong(maxTimestampMs);
+        writable.writeString(tokenId);
+        writable.writeBytes(hmac);
+        writable.writeInt(throttleTimeMs);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.errorCode = struct.getShort("error_code");
+        this.principalType = struct.getString("principal_type");
+        this.principalName = struct.getString("principal_name");
+        this.issueTimestampMs = struct.getLong("issue_timestamp_ms");
+        this.expiryTimestampMs = struct.getLong("expiry_timestamp_ms");
+        this.maxTimestampMs = struct.getLong("max_timestamp_ms");
+        this.tokenId = struct.getString("token_id");
+        this.hmac = struct.getByteArray("hmac");
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("error_code", this.errorCode);
+        struct.set("principal_type", this.principalType);
+        struct.set("principal_name", this.principalName);
+        struct.set("issue_timestamp_ms", this.issueTimestampMs);
+        struct.set("expiry_timestamp_ms", this.expiryTimestampMs);
+        struct.set("max_timestamp_ms", this.maxTimestampMs);
+        struct.set("token_id", this.tokenId);
+        struct.setByteArray("hmac", this.hmac);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 2;
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(principalType);
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(principalName);
+        size += 8;
+        size += 8;
+        size += 8;
+        size += 2;
+        size += MessageUtil.serializedUtf8Length(tokenId);
+        size += 4;
+        size += hmac.length;
+        size += 4;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateDelegationTokenResponseData)) return false;
+        CreateDelegationTokenResponseData other = (CreateDelegationTokenResponseData) obj;
+        if (errorCode != other.errorCode) return false;
+        if (this.principalType == null) {
+            if (other.principalType != null) return false;
+        } else {
+            if (!this.principalType.equals(other.principalType)) return false;
+        }
+        if (this.principalName == null) {
+            if (other.principalName != null) return false;
+        } else {
+            if (!this.principalName.equals(other.principalName)) return false;
+        }
+        if (issueTimestampMs != other.issueTimestampMs) return false;
+        if (expiryTimestampMs != other.expiryTimestampMs) return false;
+        if (maxTimestampMs != other.maxTimestampMs) return false;
+        if (this.tokenId == null) {
+            if (other.tokenId != null) return false;
+        } else {
+            if (!this.tokenId.equals(other.tokenId)) return false;
+        }
+        if (!Arrays.equals(this.hmac, other.hmac)) return false;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + errorCode;
+        hashCode = 31 * hashCode + (principalType == null ? 0 : principalType.hashCode());
+        hashCode = 31 * hashCode + (principalName == null ? 0 : principalName.hashCode());
+        hashCode = 31 * hashCode + ((int) (issueTimestampMs >> 32) ^ (int) issueTimestampMs);
+        hashCode = 31 * hashCode + ((int) (expiryTimestampMs >> 32) ^ (int) expiryTimestampMs);
+        hashCode = 31 * hashCode + ((int) (maxTimestampMs >> 32) ^ (int) maxTimestampMs);
+        hashCode = 31 * hashCode + (tokenId == null ? 0 : tokenId.hashCode());
+        hashCode = 31 * hashCode + Arrays.hashCode(hmac);
+        hashCode = 31 * hashCode + throttleTimeMs;
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateDelegationTokenResponseData("
+            + "errorCode=" + errorCode
+            + ", principalType='" + principalType + "'"
+            + ", principalName='" + principalName + "'"
+            + ", issueTimestampMs=" + issueTimestampMs
+            + ", expiryTimestampMs=" + expiryTimestampMs
+            + ", maxTimestampMs=" + maxTimestampMs
+            + ", tokenId='" + tokenId + "'"
+            + ", hmac=" + Arrays.toString(hmac)
+            + ", throttleTimeMs=" + throttleTimeMs
+            + ")";
+    }
+    
+    public short errorCode() {
+        return this.errorCode;
+    }
+    
+    public String principalType() {
+        return this.principalType;
+    }
+    
+    public String principalName() {
+        return this.principalName;
+    }
+    
+    public long issueTimestampMs() {
+        return this.issueTimestampMs;
+    }
+    
+    public long expiryTimestampMs() {
+        return this.expiryTimestampMs;
+    }
+    
+    public long maxTimestampMs() {
+        return this.maxTimestampMs;
+    }
+    
+    public String tokenId() {
+        return this.tokenId;
+    }
+    
+    public byte[] hmac() {
+        return this.hmac;
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public CreateDelegationTokenResponseData setErrorCode(short v) {
+        this.errorCode = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setPrincipalType(String v) {
+        this.principalType = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setPrincipalName(String v) {
+        this.principalName = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setIssueTimestampMs(long v) {
+        this.issueTimestampMs = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setExpiryTimestampMs(long v) {
+        this.expiryTimestampMs = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setMaxTimestampMs(long v) {
+        this.maxTimestampMs = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setTokenId(String v) {
+        this.tokenId = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setHmac(byte[] v) {
+        this.hmac = v;
+        return this;
+    }
+    
+    public CreateDelegationTokenResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsRequestData.java
new file mode 100644
index 0000000..4d33234
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsRequestData.java
@@ -0,0 +1,539 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class CreatePartitionsRequestData implements ApiMessage {
+    private List<CreatePartitionsTopic> topics;
+    private int timeoutMs;
+    private boolean validateOnly;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("topics", new ArrayOf(CreatePartitionsTopic.SCHEMA_0), "Each topic that we want to create new partitions inside."),
+            new Field("timeout_ms", Type.INT32, "The time in ms to wait for the partitions to be created."),
+            new Field("validate_only", Type.BOOLEAN, "If true, then validate the request, but don't actually increase the number of partitions.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreatePartitionsRequestData(Readable readable, short version) {
+        this.topics = new ArrayList<CreatePartitionsTopic>();
+        read(readable, version);
+    }
+    
+    public CreatePartitionsRequestData(Struct struct, short version) {
+        this.topics = new ArrayList<CreatePartitionsTopic>();
+        fromStruct(struct, version);
+    }
+    
+    public CreatePartitionsRequestData() {
+        this.topics = new ArrayList<CreatePartitionsTopic>();
+        this.timeoutMs = 0;
+        this.validateOnly = false;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 37;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.topics.clear();
+            } else {
+                this.topics.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.topics.add(new CreatePartitionsTopic(readable, version));
+                }
+            }
+        }
+        this.timeoutMs = readable.readInt();
+        this.validateOnly = readable.readByte() != 0;
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(topics.size());
+        for (CreatePartitionsTopic element : topics) {
+            element.write(writable, version);
+        }
+        writable.writeInt(timeoutMs);
+        writable.writeByte(validateOnly ? (byte) 1 : (byte) 0);
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("topics");
+            this.topics = new ArrayList<CreatePartitionsTopic>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.topics.add(new CreatePartitionsTopic((Struct) nestedObject, version));
+            }
+        }
+        this.timeoutMs = struct.getInt("timeout_ms");
+        this.validateOnly = struct.getBoolean("validate_only");
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[topics.size()];
+            int i = 0;
+            for (CreatePartitionsTopic element : this.topics) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("topics", (Object[]) nestedObjects);
+        }
+        struct.set("timeout_ms", this.timeoutMs);
+        struct.set("validate_only", this.validateOnly);
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (CreatePartitionsTopic element : topics) {
+            size += element.size(version);
+        }
+        size += 4;
+        size += 1;
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreatePartitionsRequestData)) return false;
+        CreatePartitionsRequestData other = (CreatePartitionsRequestData) obj;
+        if (this.topics == null) {
+            if (other.topics != null) return false;
+        } else {
+            if (!this.topics.equals(other.topics)) return false;
+        }
+        if (timeoutMs != other.timeoutMs) return false;
+        if (validateOnly != other.validateOnly) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (topics == null ? 0 : topics.hashCode());
+        hashCode = 31 * hashCode + timeoutMs;
+        hashCode = 31 * hashCode + (validateOnly ? 1231 : 1237);
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreatePartitionsRequestData("
+            + "topics=" + MessageUtil.deepToString(topics.iterator())
+            + ", timeoutMs=" + timeoutMs
+            + ", validateOnly=" + (validateOnly ? "true" : "false")
+            + ")";
+    }
+    
+    public List<CreatePartitionsTopic> topics() {
+        return this.topics;
+    }
+    
+    public int timeoutMs() {
+        return this.timeoutMs;
+    }
+    
+    public boolean validateOnly() {
+        return this.validateOnly;
+    }
+    
+    public CreatePartitionsRequestData setTopics(List<CreatePartitionsTopic> v) {
+        this.topics = v;
+        return this;
+    }
+    
+    public CreatePartitionsRequestData setTimeoutMs(int v) {
+        this.timeoutMs = v;
+        return this;
+    }
+    
+    public CreatePartitionsRequestData setValidateOnly(boolean v) {
+        this.validateOnly = v;
+        return this;
+    }
+    
+    static public class CreatePartitionsTopic implements Message {
+        private String name;
+        private int count;
+        private List<CreatePartitionsAssignment> assignments;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("count", Type.INT32, "The new partition count."),
+                new Field("assignments", ArrayOf.nullable(CreatePartitionsAssignment.SCHEMA_0), "The new partition assignments.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatePartitionsTopic(Readable readable, short version) {
+            this.assignments = new ArrayList<CreatePartitionsAssignment>();
+            read(readable, version);
+        }
+        
+        public CreatePartitionsTopic(Struct struct, short version) {
+            this.assignments = new ArrayList<CreatePartitionsAssignment>();
+            fromStruct(struct, version);
+        }
+        
+        public CreatePartitionsTopic() {
+            this.name = "";
+            this.count = 0;
+            this.assignments = new ArrayList<CreatePartitionsAssignment>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.count = readable.readInt();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.assignments.clear();
+                } else {
+                    this.assignments.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.assignments.add(new CreatePartitionsAssignment(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeInt(count);
+            if (assignments == null) {
+                writable.writeInt(-1);
+            } else {
+                writable.writeInt(assignments.size());
+                for (CreatePartitionsAssignment element : assignments) {
+                    element.write(writable, version);
+                }
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.count = struct.getInt("count");
+            {
+                Object[] nestedObjects = struct.getArray("assignments");
+                if (nestedObjects == null) {
+                    this.assignments = null;
+                } else {
+                    this.assignments = new ArrayList<CreatePartitionsAssignment>(nestedObjects.length);
+                    for (Object nestedObject : nestedObjects) {
+                        this.assignments.add(new CreatePartitionsAssignment((Struct) nestedObject, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("count", this.count);
+            {
+                if (assignments == null) {
+                    struct.set("assignments", null);
+                } else {
+                    Struct[] nestedObjects = new Struct[assignments.size()];
+                    int i = 0;
+                    for (CreatePartitionsAssignment element : this.assignments) {
+                        nestedObjects[i++] = element.toStruct(version);
+                    }
+                    struct.set("assignments", (Object[]) nestedObjects);
+                }
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 4;
+            if (assignments == null) {
+                size += 4;
+            } else {
+                size += 4;
+                for (CreatePartitionsAssignment element : assignments) {
+                    size += element.size(version);
+                }
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatePartitionsTopic)) return false;
+            CreatePartitionsTopic other = (CreatePartitionsTopic) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            if (count != other.count) return false;
+            if (this.assignments == null) {
+                if (other.assignments != null) return false;
+            } else {
+                if (!this.assignments.equals(other.assignments)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            hashCode = 31 * hashCode + count;
+            hashCode = 31 * hashCode + (assignments == null ? 0 : assignments.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatePartitionsTopic("
+                + "name='" + name + "'"
+                + ", count=" + count
+                + ", assignments=" + MessageUtil.deepToString(assignments.iterator())
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public int count() {
+            return this.count;
+        }
+        
+        public List<CreatePartitionsAssignment> assignments() {
+            return this.assignments;
+        }
+        
+        public CreatePartitionsTopic setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public CreatePartitionsTopic setCount(int v) {
+            this.count = v;
+            return this;
+        }
+        
+        public CreatePartitionsTopic setAssignments(List<CreatePartitionsAssignment> v) {
+            this.assignments = v;
+            return this;
+        }
+    }
+    
+    static public class CreatePartitionsAssignment implements Message {
+        private List<Integer> brokerIds;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("broker_ids", new ArrayOf(Type.INT32), "The assigned broker IDs.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatePartitionsAssignment(Readable readable, short version) {
+            this.brokerIds = new ArrayList<Integer>();
+            read(readable, version);
+        }
+        
+        public CreatePartitionsAssignment(Struct struct, short version) {
+            this.brokerIds = new ArrayList<Integer>();
+            fromStruct(struct, version);
+        }
+        
+        public CreatePartitionsAssignment() {
+            this.brokerIds = new ArrayList<Integer>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.brokerIds.clear();
+                } else {
+                    this.brokerIds.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.brokerIds.add(readable.readInt());
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeInt(brokerIds.size());
+            for (Integer element : brokerIds) {
+                writable.writeInt(element);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            {
+                Object[] nestedObjects = struct.getArray("broker_ids");
+                this.brokerIds = new ArrayList<Integer>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.brokerIds.add((Integer) nestedObject);
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            {
+                Integer[] nestedObjects = new Integer[brokerIds.size()];
+                int i = 0;
+                for (Integer element : this.brokerIds) {
+                    nestedObjects[i++] = element;
+                }
+                struct.set("broker_ids", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 4;
+            size += brokerIds.size() * 4;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatePartitionsAssignment)) return false;
+            CreatePartitionsAssignment other = (CreatePartitionsAssignment) obj;
+            if (this.brokerIds == null) {
+                if (other.brokerIds != null) return false;
+            } else {
+                if (!this.brokerIds.equals(other.brokerIds)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (brokerIds == null ? 0 : brokerIds.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatePartitionsAssignment("
+                + "brokerIds=" + MessageUtil.deepToString(brokerIds.iterator())
+                + ")";
+        }
+        
+        public List<Integer> brokerIds() {
+            return this.brokerIds;
+        }
+        
+        public CreatePartitionsAssignment setBrokerIds(List<Integer> v) {
+            this.brokerIds = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsResponseData.java
new file mode 100644
index 0000000..c04ed07
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreatePartitionsResponseData.java
@@ -0,0 +1,343 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class CreatePartitionsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private List<CreatePartitionsTopicResult> results;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("results", new ArrayOf(CreatePartitionsTopicResult.SCHEMA_0), "The partition creation results for each topic.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public CreatePartitionsResponseData(Readable readable, short version) {
+        this.results = new ArrayList<CreatePartitionsTopicResult>();
+        read(readable, version);
+    }
+    
+    public CreatePartitionsResponseData(Struct struct, short version) {
+        this.results = new ArrayList<CreatePartitionsTopicResult>();
+        fromStruct(struct, version);
+    }
+    
+    public CreatePartitionsResponseData() {
+        this.throttleTimeMs = 0;
+        this.results = new ArrayList<CreatePartitionsTopicResult>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 37;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.results.clear();
+            } else {
+                this.results.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.results.add(new CreatePartitionsTopicResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(results.size());
+        for (CreatePartitionsTopicResult element : results) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("results");
+            this.results = new ArrayList<CreatePartitionsTopicResult>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.results.add(new CreatePartitionsTopicResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[results.size()];
+            int i = 0;
+            for (CreatePartitionsTopicResult element : this.results) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("results", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (CreatePartitionsTopicResult element : results) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreatePartitionsResponseData)) return false;
+        CreatePartitionsResponseData other = (CreatePartitionsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.results == null) {
+            if (other.results != null) return false;
+        } else {
+            if (!this.results.equals(other.results)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (results == null ? 0 : results.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreatePartitionsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", results=" + MessageUtil.deepToString(results.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public List<CreatePartitionsTopicResult> results() {
+        return this.results;
+    }
+    
+    public CreatePartitionsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public CreatePartitionsResponseData setResults(List<CreatePartitionsTopicResult> v) {
+        this.results = v;
+        return this;
+    }
+    
+    static public class CreatePartitionsTopicResult implements Message {
+        private String name;
+        private short errorCode;
+        private String errorMessage;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("error_code", Type.INT16, "The result error, or zero if there was no error."),
+                new Field("error_message", Type.NULLABLE_STRING, "The result message, or null if there was no error.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public CreatePartitionsTopicResult(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreatePartitionsTopicResult(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreatePartitionsTopicResult() {
+            this.name = "";
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.errorCode = readable.readShort();
+            this.errorMessage = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeShort(errorCode);
+            writable.writeNullableString(errorMessage);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.errorCode = struct.getShort("error_code");
+            this.errorMessage = struct.getString("error_message");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("error_code", this.errorCode);
+            struct.set("error_message", this.errorMessage);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 2;
+            size += 2;
+            if (errorMessage != null) {
+                size += MessageUtil.serializedUtf8Length(errorMessage);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatePartitionsTopicResult)) return false;
+            CreatePartitionsTopicResult other = (CreatePartitionsTopicResult) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            if (errorCode != other.errorCode) return false;
+            if (this.errorMessage == null) {
+                if (other.errorMessage != null) return false;
+            } else {
+                if (!this.errorMessage.equals(other.errorMessage)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            hashCode = 31 * hashCode + errorCode;
+            hashCode = 31 * hashCode + (errorMessage == null ? 0 : errorMessage.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatePartitionsTopicResult("
+                + "name='" + name + "'"
+                + ", errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        public CreatePartitionsTopicResult setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public CreatePartitionsTopicResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public CreatePartitionsTopicResult setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsRequestData.java
new file mode 100644
index 0000000..44c9615
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsRequestData.java
@@ -0,0 +1,884 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.errors.UnsupportedVersionException;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class CreateTopicsRequestData implements ApiMessage {
+    private List<CreatableTopic> topics;
+    private int timeoutMs;
+    private boolean validateOnly;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("topics", new ArrayOf(CreatableTopic.SCHEMA_0), "The topics to create."),
+            new Field("timeout_ms", Type.INT32, "How long to wait in milliseconds before timing out the request.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("topics", new ArrayOf(CreatableTopic.SCHEMA_0), "The topics to create."),
+            new Field("timeout_ms", Type.INT32, "How long to wait in milliseconds before timing out the request."),
+            new Field("validate_only", Type.BOOLEAN, "If true, check that the topics can be created as specified, but don't create anything.")
+        );
+    
+    public static final Schema SCHEMA_2 = SCHEMA_1;
+    
+    public static final Schema SCHEMA_3 = SCHEMA_2;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2,
+        SCHEMA_3
+    };
+    
+    public CreateTopicsRequestData(Readable readable, short version) {
+        this.topics = new ArrayList<CreatableTopic>();
+        read(readable, version);
+    }
+    
+    public CreateTopicsRequestData(Struct struct, short version) {
+        this.topics = new ArrayList<CreatableTopic>();
+        fromStruct(struct, version);
+    }
+    
+    public CreateTopicsRequestData() {
+        this.topics = new ArrayList<CreatableTopic>();
+        this.timeoutMs = 0;
+        this.validateOnly = false;
+    }
+    
+    @Override
+    public short apiKey() {
+        return 19;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 3;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.topics.clear();
+            } else {
+                this.topics.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.topics.add(new CreatableTopic(readable, version));
+                }
+            }
+        }
+        this.timeoutMs = readable.readInt();
+        if (version >= 1) {
+            this.validateOnly = readable.readByte() != 0;
+        } else {
+            this.validateOnly = false;
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(topics.size());
+        for (CreatableTopic element : topics) {
+            element.write(writable, version);
+        }
+        writable.writeInt(timeoutMs);
+        if (version >= 1) {
+            writable.writeByte(validateOnly ? (byte) 1 : (byte) 0);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("topics");
+            this.topics = new ArrayList<CreatableTopic>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.topics.add(new CreatableTopic((Struct) nestedObject, version));
+            }
+        }
+        this.timeoutMs = struct.getInt("timeout_ms");
+        if (version >= 1) {
+            this.validateOnly = struct.getBoolean("validate_only");
+        } else {
+            this.validateOnly = false;
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[topics.size()];
+            int i = 0;
+            for (CreatableTopic element : this.topics) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("topics", (Object[]) nestedObjects);
+        }
+        struct.set("timeout_ms", this.timeoutMs);
+        if (version >= 1) {
+            struct.set("validate_only", this.validateOnly);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (CreatableTopic element : topics) {
+            size += element.size(version);
+        }
+        size += 4;
+        if (version >= 1) {
+            size += 1;
+        } else {
+            if (validateOnly) {
+                throw new UnsupportedVersionException("Attempted to write a non-default validateOnly at version " + version);
+            }
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateTopicsRequestData)) return false;
+        CreateTopicsRequestData other = (CreateTopicsRequestData) obj;
+        if (this.topics == null) {
+            if (other.topics != null) return false;
+        } else {
+            if (!this.topics.equals(other.topics)) return false;
+        }
+        if (timeoutMs != other.timeoutMs) return false;
+        if (validateOnly != other.validateOnly) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (topics == null ? 0 : topics.hashCode());
+        hashCode = 31 * hashCode + timeoutMs;
+        hashCode = 31 * hashCode + (validateOnly ? 1231 : 1237);
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateTopicsRequestData("
+            + "topics=" + MessageUtil.deepToString(topics.iterator())
+            + ", timeoutMs=" + timeoutMs
+            + ", validateOnly=" + (validateOnly ? "true" : "false")
+            + ")";
+    }
+    
+    public List<CreatableTopic> topics() {
+        return this.topics;
+    }
+    
+    public int timeoutMs() {
+        return this.timeoutMs;
+    }
+    
+    public boolean validateOnly() {
+        return this.validateOnly;
+    }
+    
+    public CreateTopicsRequestData setTopics(List<CreatableTopic> v) {
+        this.topics = v;
+        return this;
+    }
+    
+    public CreateTopicsRequestData setTimeoutMs(int v) {
+        this.timeoutMs = v;
+        return this;
+    }
+    
+    public CreateTopicsRequestData setValidateOnly(boolean v) {
+        this.validateOnly = v;
+        return this;
+    }
+    
+    static public class CreatableTopic implements Message {
+        private String name;
+        private int numPartitions;
+        private short replicationFactor;
+        private CreatableReplicaAssignmentSet assignments;
+        private CreateableTopicConfigSet configs;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("num_partitions", Type.INT32, "The number of partitions to create in the topic, or -1 if we are specifying a manual partition assignment."),
+                new Field("replication_factor", Type.INT16, "The number of replicas to create for each partition in the topic, or -1 if we are specifying a manual partition assignment."),
+                new Field("assignments", new ArrayOf(CreatableReplicaAssignment.SCHEMA_0), "The manual partition assignment, or the empty array if we are using automatic assignment."),
+                new Field("configs", new ArrayOf(CreateableTopicConfig.SCHEMA_0), "The custom topic configurations to set.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema SCHEMA_3 = SCHEMA_2;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2,
+            SCHEMA_3
+        };
+        
+        public CreatableTopic(Readable readable, short version) {
+            this.assignments = new CreatableReplicaAssignmentSet(0);
+            this.configs = new CreateableTopicConfigSet(0);
+            read(readable, version);
+        }
+        
+        public CreatableTopic(Struct struct, short version) {
+            this.assignments = new CreatableReplicaAssignmentSet(0);
+            this.configs = new CreateableTopicConfigSet(0);
+            fromStruct(struct, version);
+        }
+        
+        public CreatableTopic() {
+            this.name = "";
+            this.numPartitions = 0;
+            this.replicationFactor = (short) 0;
+            this.assignments = new CreatableReplicaAssignmentSet(0);
+            this.configs = new CreateableTopicConfigSet(0);
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 3;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.numPartitions = readable.readInt();
+            this.replicationFactor = readable.readShort();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.assignments.clear(0);
+                } else {
+                    this.assignments.clear(arrayLength);
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.assignments.add(new CreatableReplicaAssignment(readable, version));
+                    }
+                }
+            }
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.configs.clear(0);
+                } else {
+                    this.configs.clear(arrayLength);
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.configs.add(new CreateableTopicConfig(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeInt(numPartitions);
+            writable.writeShort(replicationFactor);
+            writable.writeInt(assignments.size());
+            for (CreatableReplicaAssignment element : assignments) {
+                element.write(writable, version);
+            }
+            writable.writeInt(configs.size());
+            for (CreateableTopicConfig element : configs) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.numPartitions = struct.getInt("num_partitions");
+            this.replicationFactor = struct.getShort("replication_factor");
+            {
+                Object[] nestedObjects = struct.getArray("assignments");
+                this.assignments = new CreatableReplicaAssignmentSet(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.assignments.add(new CreatableReplicaAssignment((Struct) nestedObject, version));
+                }
+            }
+            {
+                Object[] nestedObjects = struct.getArray("configs");
+                this.configs = new CreateableTopicConfigSet(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.configs.add(new CreateableTopicConfig((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("num_partitions", this.numPartitions);
+            struct.set("replication_factor", this.replicationFactor);
+            {
+                Struct[] nestedObjects = new Struct[assignments.size()];
+                int i = 0;
+                for (CreatableReplicaAssignment element : this.assignments) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("assignments", (Object[]) nestedObjects);
+            }
+            {
+                Struct[] nestedObjects = new Struct[configs.size()];
+                int i = 0;
+                for (CreateableTopicConfig element : this.configs) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("configs", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 4;
+            size += 2;
+            size += 4;
+            for (CreatableReplicaAssignment element : assignments) {
+                size += element.size(version);
+            }
+            size += 4;
+            for (CreateableTopicConfig element : configs) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableTopic)) return false;
+            CreatableTopic other = (CreatableTopic) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            if (numPartitions != other.numPartitions) return false;
+            if (replicationFactor != other.replicationFactor) return false;
+            if (this.assignments == null) {
+                if (other.assignments != null) return false;
+            } else {
+                if (!this.assignments.equals(other.assignments)) return false;
+            }
+            if (this.configs == null) {
+                if (other.configs != null) return false;
+            } else {
+                if (!this.configs.equals(other.configs)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            hashCode = 31 * hashCode + numPartitions;
+            hashCode = 31 * hashCode + replicationFactor;
+            hashCode = 31 * hashCode + (assignments == null ? 0 : assignments.hashCode());
+            hashCode = 31 * hashCode + (configs == null ? 0 : configs.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableTopic("
+                + "name='" + name + "'"
+                + ", numPartitions=" + numPartitions
+                + ", replicationFactor=" + replicationFactor
+                + ", assignments=" + MessageUtil.deepToString(assignments.iterator())
+                + ", configs=" + MessageUtil.deepToString(configs.iterator())
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public int numPartitions() {
+            return this.numPartitions;
+        }
+        
+        public short replicationFactor() {
+            return this.replicationFactor;
+        }
+        
+        public CreatableReplicaAssignmentSet assignments() {
+            return this.assignments;
+        }
+        
+        public CreateableTopicConfigSet configs() {
+            return this.configs;
+        }
+        
+        public CreatableTopic setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public CreatableTopic setNumPartitions(int v) {
+            this.numPartitions = v;
+            return this;
+        }
+        
+        public CreatableTopic setReplicationFactor(short v) {
+            this.replicationFactor = v;
+            return this;
+        }
+        
+        public CreatableTopic setAssignments(CreatableReplicaAssignmentSet v) {
+            this.assignments = v;
+            return this;
+        }
+        
+        public CreatableTopic setConfigs(CreateableTopicConfigSet v) {
+            this.configs = v;
+            return this;
+        }
+    }
+    
+    static public class CreatableReplicaAssignment implements Message, ImplicitLinkedHashMultiSet.Element {
+        private int partitionIndex;
+        private List<Integer> brokerIds;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("partition_index", Type.INT32, "The partition index."),
+                new Field("broker_ids", new ArrayOf(Type.INT32), "The brokers to place the partition on.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema SCHEMA_3 = SCHEMA_2;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2,
+            SCHEMA_3
+        };
+        
+        public CreatableReplicaAssignment(Readable readable, short version) {
+            this.brokerIds = new ArrayList<Integer>();
+            read(readable, version);
+        }
+        
+        public CreatableReplicaAssignment(Struct struct, short version) {
+            this.brokerIds = new ArrayList<Integer>();
+            fromStruct(struct, version);
+        }
+        
+        public CreatableReplicaAssignment() {
+            this.partitionIndex = 0;
+            this.brokerIds = new ArrayList<Integer>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 3;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.partitionIndex = readable.readInt();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.brokerIds.clear();
+                } else {
+                    this.brokerIds.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.brokerIds.add(readable.readInt());
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeInt(partitionIndex);
+            writable.writeInt(brokerIds.size());
+            for (Integer element : brokerIds) {
+                writable.writeInt(element);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.partitionIndex = struct.getInt("partition_index");
+            {
+                Object[] nestedObjects = struct.getArray("broker_ids");
+                this.brokerIds = new ArrayList<Integer>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.brokerIds.add((Integer) nestedObject);
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("partition_index", this.partitionIndex);
+            {
+                Integer[] nestedObjects = new Integer[brokerIds.size()];
+                int i = 0;
+                for (Integer element : this.brokerIds) {
+                    nestedObjects[i++] = element;
+                }
+                struct.set("broker_ids", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 4;
+            size += 4;
+            size += brokerIds.size() * 4;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableReplicaAssignment)) return false;
+            CreatableReplicaAssignment other = (CreatableReplicaAssignment) obj;
+            if (partitionIndex != other.partitionIndex) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + partitionIndex;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableReplicaAssignment("
+                + "partitionIndex=" + partitionIndex
+                + ", brokerIds=" + MessageUtil.deepToString(brokerIds.iterator())
+                + ")";
+        }
+        
+        public int partitionIndex() {
+            return this.partitionIndex;
+        }
+        
+        public List<Integer> brokerIds() {
+            return this.brokerIds;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public CreatableReplicaAssignment setPartitionIndex(int v) {
+            this.partitionIndex = v;
+            return this;
+        }
+        
+        public CreatableReplicaAssignment setBrokerIds(List<Integer> v) {
+            this.brokerIds = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class CreatableReplicaAssignmentSet extends ImplicitLinkedHashMultiSet<CreatableReplicaAssignment> {
+        public CreatableReplicaAssignmentSet() {
+            super();
+        }
+        
+        public CreatableReplicaAssignmentSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public CreatableReplicaAssignmentSet(Iterator<CreatableReplicaAssignment> iterator) {
+            super(iterator);
+        }
+        
+        public CreatableReplicaAssignment find(int partitionIndex) {
+            CreatableReplicaAssignment key = new CreatableReplicaAssignment();
+            key.setPartitionIndex(partitionIndex);
+            return find(key);
+        }
+        
+        public List<CreatableReplicaAssignment> findAll(int partitionIndex) {
+            CreatableReplicaAssignment key = new CreatableReplicaAssignment();
+            key.setPartitionIndex(partitionIndex);
+            return findAll(key);
+        }
+        
+    }
+    
+    static public class CreateableTopicConfig implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private String value;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The configuration name."),
+                new Field("value", Type.NULLABLE_STRING, "The configuration value.")
+            );
+        
+        public static final Schema SCHEMA_1 = SCHEMA_0;
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema SCHEMA_3 = SCHEMA_2;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2,
+            SCHEMA_3
+        };
+        
+        public CreateableTopicConfig(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreateableTopicConfig(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreateableTopicConfig() {
+            this.name = "";
+            this.value = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 3;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.value = readable.readNullableString();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeNullableString(value);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.value = struct.getString("value");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("value", this.value);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 2;
+            if (value != null) {
+                size += MessageUtil.serializedUtf8Length(value);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreateableTopicConfig)) return false;
+            CreateableTopicConfig other = (CreateableTopicConfig) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreateableTopicConfig("
+                + "name='" + name + "'"
+                + ", value='" + value + "'"
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public String value() {
+            return this.value;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public CreateableTopicConfig setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public CreateableTopicConfig setValue(String v) {
+            this.value = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class CreateableTopicConfigSet extends ImplicitLinkedHashMultiSet<CreateableTopicConfig> {
+        public CreateableTopicConfigSet() {
+            super();
+        }
+        
+        public CreateableTopicConfigSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public CreateableTopicConfigSet(Iterator<CreateableTopicConfig> iterator) {
+            super(iterator);
+        }
+        
+        public CreateableTopicConfig find(String name) {
+            CreateableTopicConfig key = new CreateableTopicConfig();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<CreateableTopicConfig> findAll(String name) {
+            CreateableTopicConfig key = new CreateableTopicConfig();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsResponseData.java
new file mode 100644
index 0000000..ae35c83
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/CreateTopicsResponseData.java
@@ -0,0 +1,435 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+import org.apache.kafka.common.utils.ImplicitLinkedHashMultiSet;
+
+
+public class CreateTopicsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private CreatableTopicResultSet topics;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("topics", new ArrayOf(CreatableTopicResult.SCHEMA_0), "Results for each topic we tried to create.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("topics", new ArrayOf(CreatableTopicResult.SCHEMA_1), "Results for each topic we tried to create.")
+        );
+    
+    public static final Schema SCHEMA_2 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("topics", new ArrayOf(CreatableTopicResult.SCHEMA_1), "Results for each topic we tried to create.")
+        );
+    
+    public static final Schema SCHEMA_3 = SCHEMA_2;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1,
+        SCHEMA_2,
+        SCHEMA_3
+    };
+    
+    public CreateTopicsResponseData(Readable readable, short version) {
+        this.topics = new CreatableTopicResultSet(0);
+        read(readable, version);
+    }
+    
+    public CreateTopicsResponseData(Struct struct, short version) {
+        this.topics = new CreatableTopicResultSet(0);
+        fromStruct(struct, version);
+    }
+    
+    public CreateTopicsResponseData() {
+        this.throttleTimeMs = 0;
+        this.topics = new CreatableTopicResultSet(0);
+    }
+    
+    @Override
+    public short apiKey() {
+        return 19;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 3;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        if (version >= 2) {
+            this.throttleTimeMs = readable.readInt();
+        } else {
+            this.throttleTimeMs = 0;
+        }
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.topics.clear(0);
+            } else {
+                this.topics.clear(arrayLength);
+                for (int i = 0; i < arrayLength; i++) {
+                    this.topics.add(new CreatableTopicResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        if (version >= 2) {
+            writable.writeInt(throttleTimeMs);
+        }
+        writable.writeInt(topics.size());
+        for (CreatableTopicResult element : topics) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        if (version >= 2) {
+            this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        } else {
+            this.throttleTimeMs = 0;
+        }
+        {
+            Object[] nestedObjects = struct.getArray("topics");
+            this.topics = new CreatableTopicResultSet(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.topics.add(new CreatableTopicResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        if (version >= 2) {
+            struct.set("throttle_time_ms", this.throttleTimeMs);
+        }
+        {
+            Struct[] nestedObjects = new Struct[topics.size()];
+            int i = 0;
+            for (CreatableTopicResult element : this.topics) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("topics", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        if (version >= 2) {
+            size += 4;
+        }
+        size += 4;
+        for (CreatableTopicResult element : topics) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CreateTopicsResponseData)) return false;
+        CreateTopicsResponseData other = (CreateTopicsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.topics == null) {
+            if (other.topics != null) return false;
+        } else {
+            if (!this.topics.equals(other.topics)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (topics == null ? 0 : topics.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "CreateTopicsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", topics=" + MessageUtil.deepToString(topics.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public CreatableTopicResultSet topics() {
+        return this.topics;
+    }
+    
+    public CreateTopicsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public CreateTopicsResponseData setTopics(CreatableTopicResultSet v) {
+        this.topics = v;
+        return this;
+    }
+    
+    static public class CreatableTopicResult implements Message, ImplicitLinkedHashMultiSet.Element {
+        private String name;
+        private short errorCode;
+        private String errorMessage;
+        private int next;
+        private int prev;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("error_code", Type.INT16, "The error code, or 0 if there was no error.")
+            );
+        
+        public static final Schema SCHEMA_1 =
+            new Schema(
+                new Field("name", Type.STRING, "The topic name."),
+                new Field("error_code", Type.INT16, "The error code, or 0 if there was no error."),
+                new Field("error_message", Type.NULLABLE_STRING, "The error message, or null if there was no error.")
+            );
+        
+        public static final Schema SCHEMA_2 = SCHEMA_1;
+        
+        public static final Schema SCHEMA_3 = SCHEMA_2;
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1,
+            SCHEMA_2,
+            SCHEMA_3
+        };
+        
+        public CreatableTopicResult(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public CreatableTopicResult(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public CreatableTopicResult() {
+            this.name = "";
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 3;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.name = readable.readNullableString();
+            this.errorCode = readable.readShort();
+            if (version >= 1) {
+                this.errorMessage = readable.readNullableString();
+            } else {
+                this.errorMessage = "";
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeString(name);
+            writable.writeShort(errorCode);
+            if (version >= 1) {
+                writable.writeNullableString(errorMessage);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.name = struct.getString("name");
+            this.errorCode = struct.getShort("error_code");
+            if (version >= 1) {
+                this.errorMessage = struct.getString("error_message");
+            } else {
+                this.errorMessage = "";
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("name", this.name);
+            struct.set("error_code", this.errorCode);
+            if (version >= 1) {
+                struct.set("error_message", this.errorMessage);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(name);
+            size += 2;
+            if (version >= 1) {
+                size += 2;
+                if (errorMessage != null) {
+                    size += MessageUtil.serializedUtf8Length(errorMessage);
+                }
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof CreatableTopicResult)) return false;
+            CreatableTopicResult other = (CreatableTopicResult) obj;
+            if (this.name == null) {
+                if (other.name != null) return false;
+            } else {
+                if (!this.name.equals(other.name)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "CreatableTopicResult("
+                + "name='" + name + "'"
+                + ", errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ")";
+        }
+        
+        public String name() {
+            return this.name;
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        @Override
+        public int next() {
+            return this.next;
+        }
+        
+        @Override
+        public int prev() {
+            return this.prev;
+        }
+        
+        public CreatableTopicResult setName(String v) {
+            this.name = v;
+            return this;
+        }
+        
+        public CreatableTopicResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public CreatableTopicResult setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+        
+        @Override
+        public void setNext(int v) {
+            this.next = v;
+        }
+        
+        @Override
+        public void setPrev(int v) {
+            this.prev = v;
+        }
+    }
+    
+    public static class CreatableTopicResultSet extends ImplicitLinkedHashMultiSet<CreatableTopicResult> {
+        public CreatableTopicResultSet() {
+            super();
+        }
+        
+        public CreatableTopicResultSet(int expectedNumElements) {
+            super(expectedNumElements);
+        }
+        
+        public CreatableTopicResultSet(Iterator<CreatableTopicResult> iterator) {
+            super(iterator);
+        }
+        
+        public CreatableTopicResult find(String name) {
+            CreatableTopicResult key = new CreatableTopicResult();
+            key.setName(name);
+            return find(key);
+        }
+        
+        public List<CreatableTopicResult> findAll(String name) {
+            CreatableTopicResult key = new CreatableTopicResult();
+            key.setName(name);
+            return findAll(key);
+        }
+        
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsRequestData.java
new file mode 100644
index 0000000..af3ae8a
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsRequestData.java
@@ -0,0 +1,442 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.errors.UnsupportedVersionException;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class DeleteAclsRequestData implements ApiMessage {
+    private List<DeleteAclsFilter> filters;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("filters", new ArrayOf(DeleteAclsFilter.SCHEMA_0), "The filters to use when deleting ACLs.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("filters", new ArrayOf(DeleteAclsFilter.SCHEMA_1), "The filters to use when deleting ACLs.")
+        );
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public DeleteAclsRequestData(Readable readable, short version) {
+        this.filters = new ArrayList<DeleteAclsFilter>();
+        read(readable, version);
+    }
+    
+    public DeleteAclsRequestData(Struct struct, short version) {
+        this.filters = new ArrayList<DeleteAclsFilter>();
+        fromStruct(struct, version);
+    }
+    
+    public DeleteAclsRequestData() {
+        this.filters = new ArrayList<DeleteAclsFilter>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 31;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.filters.clear();
+            } else {
+                this.filters.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.filters.add(new DeleteAclsFilter(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(filters.size());
+        for (DeleteAclsFilter element : filters) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("filters");
+            this.filters = new ArrayList<DeleteAclsFilter>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.filters.add(new DeleteAclsFilter((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            Struct[] nestedObjects = new Struct[filters.size()];
+            int i = 0;
+            for (DeleteAclsFilter element : this.filters) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("filters", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (DeleteAclsFilter element : filters) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DeleteAclsRequestData)) return false;
+        DeleteAclsRequestData other = (DeleteAclsRequestData) obj;
+        if (this.filters == null) {
+            if (other.filters != null) return false;
+        } else {
+            if (!this.filters.equals(other.filters)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (filters == null ? 0 : filters.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "DeleteAclsRequestData("
+            + "filters=" + MessageUtil.deepToString(filters.iterator())
+            + ")";
+    }
+    
+    public List<DeleteAclsFilter> filters() {
+        return this.filters;
+    }
+    
+    public DeleteAclsRequestData setFilters(List<DeleteAclsFilter> v) {
+        this.filters = v;
+        return this;
+    }
+    
+    static public class DeleteAclsFilter implements Message {
+        private byte resourceTypeFilter;
+        private String resourceNameFilter;
+        private byte patternTypeFilter;
+        private String principalFilter;
+        private String hostFilter;
+        private byte operation;
+        private byte permissionType;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("resource_type_filter", Type.INT8, "The resource type."),
+                new Field("resource_name_filter", Type.NULLABLE_STRING, "The resource name."),
+                new Field("principal_filter", Type.NULLABLE_STRING, "The principal filter, or null to accept all principals."),
+                new Field("host_filter", Type.NULLABLE_STRING, "The host filter, or null to accept all hosts."),
+                new Field("operation", Type.INT8, "The ACL operation."),
+                new Field("permission_type", Type.INT8, "The permission type.")
+            );
+        
+        public static final Schema SCHEMA_1 =
+            new Schema(
+                new Field("resource_type_filter", Type.INT8, "The resource type."),
+                new Field("resource_name_filter", Type.NULLABLE_STRING, "The resource name."),
+                new Field("pattern_type_filter", Type.INT8, "The pattern type."),
+                new Field("principal_filter", Type.NULLABLE_STRING, "The principal filter, or null to accept all principals."),
+                new Field("host_filter", Type.NULLABLE_STRING, "The host filter, or null to accept all hosts."),
+                new Field("operation", Type.INT8, "The ACL operation."),
+                new Field("permission_type", Type.INT8, "The permission type.")
+            );
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public DeleteAclsFilter(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public DeleteAclsFilter(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public DeleteAclsFilter() {
+            this.resourceTypeFilter = (byte) 0;
+            this.resourceNameFilter = "";
+            this.patternTypeFilter = (byte) 3;
+            this.principalFilter = "";
+            this.hostFilter = "";
+            this.operation = (byte) 0;
+            this.permissionType = (byte) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.resourceTypeFilter = readable.readByte();
+            this.resourceNameFilter = readable.readNullableString();
+            if (version >= 1) {
+                this.patternTypeFilter = readable.readByte();
+            } else {
+                this.patternTypeFilter = (byte) 3;
+            }
+            this.principalFilter = readable.readNullableString();
+            this.hostFilter = readable.readNullableString();
+            this.operation = readable.readByte();
+            this.permissionType = readable.readByte();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeByte(resourceTypeFilter);
+            writable.writeNullableString(resourceNameFilter);
+            if (version >= 1) {
+                writable.writeByte(patternTypeFilter);
+            }
+            writable.writeNullableString(principalFilter);
+            writable.writeNullableString(hostFilter);
+            writable.writeByte(operation);
+            writable.writeByte(permissionType);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.resourceTypeFilter = struct.getByte("resource_type_filter");
+            this.resourceNameFilter = struct.getString("resource_name_filter");
+            if (version >= 1) {
+                this.patternTypeFilter = struct.getByte("pattern_type_filter");
+            } else {
+                this.patternTypeFilter = (byte) 3;
+            }
+            this.principalFilter = struct.getString("principal_filter");
+            this.hostFilter = struct.getString("host_filter");
+            this.operation = struct.getByte("operation");
+            this.permissionType = struct.getByte("permission_type");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("resource_type_filter", this.resourceTypeFilter);
+            struct.set("resource_name_filter", this.resourceNameFilter);
+            if (version >= 1) {
+                struct.set("pattern_type_filter", this.patternTypeFilter);
+            }
+            struct.set("principal_filter", this.principalFilter);
+            struct.set("host_filter", this.hostFilter);
+            struct.set("operation", this.operation);
+            struct.set("permission_type", this.permissionType);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 1;
+            size += 2;
+            if (resourceNameFilter != null) {
+                size += MessageUtil.serializedUtf8Length(resourceNameFilter);
+            }
+            if (version >= 1) {
+                size += 1;
+            } else {
+                if (patternTypeFilter != (byte) 3) {
+                    throw new UnsupportedVersionException("Attempted to write a non-default patternTypeFilter at version " + version);
+                }
+            }
+            size += 2;
+            if (principalFilter != null) {
+                size += MessageUtil.serializedUtf8Length(principalFilter);
+            }
+            size += 2;
+            if (hostFilter != null) {
+                size += MessageUtil.serializedUtf8Length(hostFilter);
+            }
+            size += 1;
+            size += 1;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof DeleteAclsFilter)) return false;
+            DeleteAclsFilter other = (DeleteAclsFilter) obj;
+            if (resourceTypeFilter != other.resourceTypeFilter) return false;
+            if (this.resourceNameFilter == null) {
+                if (other.resourceNameFilter != null) return false;
+            } else {
+                if (!this.resourceNameFilter.equals(other.resourceNameFilter)) return false;
+            }
+            if (patternTypeFilter != other.patternTypeFilter) return false;
+            if (this.principalFilter == null) {
+                if (other.principalFilter != null) return false;
+            } else {
+                if (!this.principalFilter.equals(other.principalFilter)) return false;
+            }
+            if (this.hostFilter == null) {
+                if (other.hostFilter != null) return false;
+            } else {
+                if (!this.hostFilter.equals(other.hostFilter)) return false;
+            }
+            if (operation != other.operation) return false;
+            if (permissionType != other.permissionType) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + resourceTypeFilter;
+            hashCode = 31 * hashCode + (resourceNameFilter == null ? 0 : resourceNameFilter.hashCode());
+            hashCode = 31 * hashCode + patternTypeFilter;
+            hashCode = 31 * hashCode + (principalFilter == null ? 0 : principalFilter.hashCode());
+            hashCode = 31 * hashCode + (hostFilter == null ? 0 : hostFilter.hashCode());
+            hashCode = 31 * hashCode + operation;
+            hashCode = 31 * hashCode + permissionType;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "DeleteAclsFilter("
+                + "resourceTypeFilter=" + resourceTypeFilter
+                + ", resourceNameFilter='" + resourceNameFilter + "'"
+                + ", patternTypeFilter=" + patternTypeFilter
+                + ", principalFilter='" + principalFilter + "'"
+                + ", hostFilter='" + hostFilter + "'"
+                + ", operation=" + operation
+                + ", permissionType=" + permissionType
+                + ")";
+        }
+        
+        public byte resourceTypeFilter() {
+            return this.resourceTypeFilter;
+        }
+        
+        public String resourceNameFilter() {
+            return this.resourceNameFilter;
+        }
+        
+        public byte patternTypeFilter() {
+            return this.patternTypeFilter;
+        }
+        
+        public String principalFilter() {
+            return this.principalFilter;
+        }
+        
+        public String hostFilter() {
+            return this.hostFilter;
+        }
+        
+        public byte operation() {
+            return this.operation;
+        }
+        
+        public byte permissionType() {
+            return this.permissionType;
+        }
+        
+        public DeleteAclsFilter setResourceTypeFilter(byte v) {
+            this.resourceTypeFilter = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setResourceNameFilter(String v) {
+            this.resourceNameFilter = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setPatternTypeFilter(byte v) {
+            this.patternTypeFilter = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setPrincipalFilter(String v) {
+            this.principalFilter = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setHostFilter(String v) {
+            this.hostFilter = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setOperation(byte v) {
+            this.operation = v;
+            return this;
+        }
+        
+        public DeleteAclsFilter setPermissionType(byte v) {
+            this.permissionType = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsResponseData.java
new file mode 100644
index 0000000..aa4ddf7
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/DeleteAclsResponseData.java
@@ -0,0 +1,692 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.errors.UnsupportedVersionException;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.Message;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class DeleteAclsResponseData implements ApiMessage {
+    private int throttleTimeMs;
+    private List<DeleteAclsFilterResult> filterResults;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("filter_results", new ArrayOf(DeleteAclsFilterResult.SCHEMA_0), "The results for each filter.")
+        );
+    
+    public static final Schema SCHEMA_1 =
+        new Schema(
+            new Field("throttle_time_ms", Type.INT32, "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota."),
+            new Field("filter_results", new ArrayOf(DeleteAclsFilterResult.SCHEMA_1), "The results for each filter.")
+        );
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public DeleteAclsResponseData(Readable readable, short version) {
+        this.filterResults = new ArrayList<DeleteAclsFilterResult>();
+        read(readable, version);
+    }
+    
+    public DeleteAclsResponseData(Struct struct, short version) {
+        this.filterResults = new ArrayList<DeleteAclsFilterResult>();
+        fromStruct(struct, version);
+    }
+    
+    public DeleteAclsResponseData() {
+        this.throttleTimeMs = 0;
+        this.filterResults = new ArrayList<DeleteAclsFilterResult>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 31;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        this.throttleTimeMs = readable.readInt();
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.filterResults.clear();
+            } else {
+                this.filterResults.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.filterResults.add(new DeleteAclsFilterResult(readable, version));
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(throttleTimeMs);
+        writable.writeInt(filterResults.size());
+        for (DeleteAclsFilterResult element : filterResults) {
+            element.write(writable, version);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        this.throttleTimeMs = struct.getInt("throttle_time_ms");
+        {
+            Object[] nestedObjects = struct.getArray("filter_results");
+            this.filterResults = new ArrayList<DeleteAclsFilterResult>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.filterResults.add(new DeleteAclsFilterResult((Struct) nestedObject, version));
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        struct.set("throttle_time_ms", this.throttleTimeMs);
+        {
+            Struct[] nestedObjects = new Struct[filterResults.size()];
+            int i = 0;
+            for (DeleteAclsFilterResult element : this.filterResults) {
+                nestedObjects[i++] = element.toStruct(version);
+            }
+            struct.set("filter_results", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        size += 4;
+        for (DeleteAclsFilterResult element : filterResults) {
+            size += element.size(version);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DeleteAclsResponseData)) return false;
+        DeleteAclsResponseData other = (DeleteAclsResponseData) obj;
+        if (throttleTimeMs != other.throttleTimeMs) return false;
+        if (this.filterResults == null) {
+            if (other.filterResults != null) return false;
+        } else {
+            if (!this.filterResults.equals(other.filterResults)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + throttleTimeMs;
+        hashCode = 31 * hashCode + (filterResults == null ? 0 : filterResults.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "DeleteAclsResponseData("
+            + "throttleTimeMs=" + throttleTimeMs
+            + ", filterResults=" + MessageUtil.deepToString(filterResults.iterator())
+            + ")";
+    }
+    
+    public int throttleTimeMs() {
+        return this.throttleTimeMs;
+    }
+    
+    public List<DeleteAclsFilterResult> filterResults() {
+        return this.filterResults;
+    }
+    
+    public DeleteAclsResponseData setThrottleTimeMs(int v) {
+        this.throttleTimeMs = v;
+        return this;
+    }
+    
+    public DeleteAclsResponseData setFilterResults(List<DeleteAclsFilterResult> v) {
+        this.filterResults = v;
+        return this;
+    }
+    
+    static public class DeleteAclsFilterResult implements Message {
+        private short errorCode;
+        private String errorMessage;
+        private List<DeleteAclsMatchingAcl> matchingAcls;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The error code, or 0 if the filter succeeded."),
+                new Field("error_message", Type.NULLABLE_STRING, "The error message, or null if the filter succeeded."),
+                new Field("matching_acls", new ArrayOf(DeleteAclsMatchingAcl.SCHEMA_0), "The ACLs which matched this filter.")
+            );
+        
+        public static final Schema SCHEMA_1 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The error code, or 0 if the filter succeeded."),
+                new Field("error_message", Type.NULLABLE_STRING, "The error message, or null if the filter succeeded."),
+                new Field("matching_acls", new ArrayOf(DeleteAclsMatchingAcl.SCHEMA_1), "The ACLs which matched this filter.")
+            );
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public DeleteAclsFilterResult(Readable readable, short version) {
+            this.matchingAcls = new ArrayList<DeleteAclsMatchingAcl>();
+            read(readable, version);
+        }
+        
+        public DeleteAclsFilterResult(Struct struct, short version) {
+            this.matchingAcls = new ArrayList<DeleteAclsMatchingAcl>();
+            fromStruct(struct, version);
+        }
+        
+        public DeleteAclsFilterResult() {
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+            this.matchingAcls = new ArrayList<DeleteAclsMatchingAcl>();
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.errorCode = readable.readShort();
+            this.errorMessage = readable.readNullableString();
+            {
+                int arrayLength = readable.readInt();
+                if (arrayLength < 0) {
+                    this.matchingAcls.clear();
+                } else {
+                    this.matchingAcls.clear();
+                    for (int i = 0; i < arrayLength; i++) {
+                        this.matchingAcls.add(new DeleteAclsMatchingAcl(readable, version));
+                    }
+                }
+            }
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeShort(errorCode);
+            writable.writeNullableString(errorMessage);
+            writable.writeInt(matchingAcls.size());
+            for (DeleteAclsMatchingAcl element : matchingAcls) {
+                element.write(writable, version);
+            }
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.errorCode = struct.getShort("error_code");
+            this.errorMessage = struct.getString("error_message");
+            {
+                Object[] nestedObjects = struct.getArray("matching_acls");
+                this.matchingAcls = new ArrayList<DeleteAclsMatchingAcl>(nestedObjects.length);
+                for (Object nestedObject : nestedObjects) {
+                    this.matchingAcls.add(new DeleteAclsMatchingAcl((Struct) nestedObject, version));
+                }
+            }
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("error_code", this.errorCode);
+            struct.set("error_message", this.errorMessage);
+            {
+                Struct[] nestedObjects = new Struct[matchingAcls.size()];
+                int i = 0;
+                for (DeleteAclsMatchingAcl element : this.matchingAcls) {
+                    nestedObjects[i++] = element.toStruct(version);
+                }
+                struct.set("matching_acls", (Object[]) nestedObjects);
+            }
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += 2;
+            if (errorMessage != null) {
+                size += MessageUtil.serializedUtf8Length(errorMessage);
+            }
+            size += 4;
+            for (DeleteAclsMatchingAcl element : matchingAcls) {
+                size += element.size(version);
+            }
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof DeleteAclsFilterResult)) return false;
+            DeleteAclsFilterResult other = (DeleteAclsFilterResult) obj;
+            if (errorCode != other.errorCode) return false;
+            if (this.errorMessage == null) {
+                if (other.errorMessage != null) return false;
+            } else {
+                if (!this.errorMessage.equals(other.errorMessage)) return false;
+            }
+            if (this.matchingAcls == null) {
+                if (other.matchingAcls != null) return false;
+            } else {
+                if (!this.matchingAcls.equals(other.matchingAcls)) return false;
+            }
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + errorCode;
+            hashCode = 31 * hashCode + (errorMessage == null ? 0 : errorMessage.hashCode());
+            hashCode = 31 * hashCode + (matchingAcls == null ? 0 : matchingAcls.hashCode());
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "DeleteAclsFilterResult("
+                + "errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ", matchingAcls=" + MessageUtil.deepToString(matchingAcls.iterator())
+                + ")";
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        public List<DeleteAclsMatchingAcl> matchingAcls() {
+            return this.matchingAcls;
+        }
+        
+        public DeleteAclsFilterResult setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public DeleteAclsFilterResult setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+        
+        public DeleteAclsFilterResult setMatchingAcls(List<DeleteAclsMatchingAcl> v) {
+            this.matchingAcls = v;
+            return this;
+        }
+    }
+    
+    static public class DeleteAclsMatchingAcl implements Message {
+        private short errorCode;
+        private String errorMessage;
+        private byte resourceType;
+        private String resourceName;
+        private byte patternType;
+        private String principal;
+        private String host;
+        private byte operation;
+        private byte permissionType;
+        
+        public static final Schema SCHEMA_0 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The deletion error code, or 0 if the deletion succeeded."),
+                new Field("error_message", Type.NULLABLE_STRING, "The deletion error message, or null if the deletion succeeded."),
+                new Field("resource_type", Type.INT8, "The ACL resource type."),
+                new Field("resource_name", Type.STRING, "The ACL resource name."),
+                new Field("principal", Type.STRING, "The ACL principal."),
+                new Field("host", Type.STRING, "The ACL host."),
+                new Field("operation", Type.INT8, "The ACL operation."),
+                new Field("permission_type", Type.INT8, "The ACL permission type.")
+            );
+        
+        public static final Schema SCHEMA_1 =
+            new Schema(
+                new Field("error_code", Type.INT16, "The deletion error code, or 0 if the deletion succeeded."),
+                new Field("error_message", Type.NULLABLE_STRING, "The deletion error message, or null if the deletion succeeded."),
+                new Field("resource_type", Type.INT8, "The ACL resource type."),
+                new Field("resource_name", Type.STRING, "The ACL resource name."),
+                new Field("pattern_type", Type.INT8, "The ACL resource pattern type."),
+                new Field("principal", Type.STRING, "The ACL principal."),
+                new Field("host", Type.STRING, "The ACL host."),
+                new Field("operation", Type.INT8, "The ACL operation."),
+                new Field("permission_type", Type.INT8, "The ACL permission type.")
+            );
+        
+        public static final Schema[] SCHEMAS = new Schema[] {
+            SCHEMA_0,
+            SCHEMA_1
+        };
+        
+        public DeleteAclsMatchingAcl(Readable readable, short version) {
+            read(readable, version);
+        }
+        
+        public DeleteAclsMatchingAcl(Struct struct, short version) {
+            fromStruct(struct, version);
+        }
+        
+        public DeleteAclsMatchingAcl() {
+            this.errorCode = (short) 0;
+            this.errorMessage = "";
+            this.resourceType = (byte) 0;
+            this.resourceName = "";
+            this.patternType = (byte) 3;
+            this.principal = "";
+            this.host = "";
+            this.operation = (byte) 0;
+            this.permissionType = (byte) 0;
+        }
+        
+        
+        @Override
+        public short lowestSupportedVersion() {
+            return 0;
+        }
+        
+        @Override
+        public short highestSupportedVersion() {
+            return 1;
+        }
+        
+        @Override
+        public void read(Readable readable, short version) {
+            this.errorCode = readable.readShort();
+            this.errorMessage = readable.readNullableString();
+            this.resourceType = readable.readByte();
+            this.resourceName = readable.readNullableString();
+            if (version >= 1) {
+                this.patternType = readable.readByte();
+            } else {
+                this.patternType = (byte) 3;
+            }
+            this.principal = readable.readNullableString();
+            this.host = readable.readNullableString();
+            this.operation = readable.readByte();
+            this.permissionType = readable.readByte();
+        }
+        
+        @Override
+        public void write(Writable writable, short version) {
+            writable.writeShort(errorCode);
+            writable.writeNullableString(errorMessage);
+            writable.writeByte(resourceType);
+            writable.writeString(resourceName);
+            if (version >= 1) {
+                writable.writeByte(patternType);
+            }
+            writable.writeString(principal);
+            writable.writeString(host);
+            writable.writeByte(operation);
+            writable.writeByte(permissionType);
+        }
+        
+        @Override
+        public void fromStruct(Struct struct, short version) {
+            this.errorCode = struct.getShort("error_code");
+            this.errorMessage = struct.getString("error_message");
+            this.resourceType = struct.getByte("resource_type");
+            this.resourceName = struct.getString("resource_name");
+            if (version >= 1) {
+                this.patternType = struct.getByte("pattern_type");
+            } else {
+                this.patternType = (byte) 3;
+            }
+            this.principal = struct.getString("principal");
+            this.host = struct.getString("host");
+            this.operation = struct.getByte("operation");
+            this.permissionType = struct.getByte("permission_type");
+        }
+        
+        @Override
+        public Struct toStruct(short version) {
+            Struct struct = new Struct(SCHEMAS[version]);
+            struct.set("error_code", this.errorCode);
+            struct.set("error_message", this.errorMessage);
+            struct.set("resource_type", this.resourceType);
+            struct.set("resource_name", this.resourceName);
+            if (version >= 1) {
+                struct.set("pattern_type", this.patternType);
+            }
+            struct.set("principal", this.principal);
+            struct.set("host", this.host);
+            struct.set("operation", this.operation);
+            struct.set("permission_type", this.permissionType);
+            return struct;
+        }
+        
+        @Override
+        public int size(short version) {
+            int size = 0;
+            size += 2;
+            size += 2;
+            if (errorMessage != null) {
+                size += MessageUtil.serializedUtf8Length(errorMessage);
+            }
+            size += 1;
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(resourceName);
+            if (version >= 1) {
+                size += 1;
+            } else {
+                if (patternType != (byte) 3) {
+                    throw new UnsupportedVersionException("Attempted to write a non-default patternType at version " + version);
+                }
+            }
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(principal);
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(host);
+            size += 1;
+            size += 1;
+            return size;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof DeleteAclsMatchingAcl)) return false;
+            DeleteAclsMatchingAcl other = (DeleteAclsMatchingAcl) obj;
+            if (errorCode != other.errorCode) return false;
+            if (this.errorMessage == null) {
+                if (other.errorMessage != null) return false;
+            } else {
+                if (!this.errorMessage.equals(other.errorMessage)) return false;
+            }
+            if (resourceType != other.resourceType) return false;
+            if (this.resourceName == null) {
+                if (other.resourceName != null) return false;
+            } else {
+                if (!this.resourceName.equals(other.resourceName)) return false;
+            }
+            if (patternType != other.patternType) return false;
+            if (this.principal == null) {
+                if (other.principal != null) return false;
+            } else {
+                if (!this.principal.equals(other.principal)) return false;
+            }
+            if (this.host == null) {
+                if (other.host != null) return false;
+            } else {
+                if (!this.host.equals(other.host)) return false;
+            }
+            if (operation != other.operation) return false;
+            if (permissionType != other.permissionType) return false;
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            int hashCode = 0;
+            hashCode = 31 * hashCode + errorCode;
+            hashCode = 31 * hashCode + (errorMessage == null ? 0 : errorMessage.hashCode());
+            hashCode = 31 * hashCode + resourceType;
+            hashCode = 31 * hashCode + (resourceName == null ? 0 : resourceName.hashCode());
+            hashCode = 31 * hashCode + patternType;
+            hashCode = 31 * hashCode + (principal == null ? 0 : principal.hashCode());
+            hashCode = 31 * hashCode + (host == null ? 0 : host.hashCode());
+            hashCode = 31 * hashCode + operation;
+            hashCode = 31 * hashCode + permissionType;
+            return hashCode;
+        }
+        
+        @Override
+        public String toString() {
+            return "DeleteAclsMatchingAcl("
+                + "errorCode=" + errorCode
+                + ", errorMessage='" + errorMessage + "'"
+                + ", resourceType=" + resourceType
+                + ", resourceName='" + resourceName + "'"
+                + ", patternType=" + patternType
+                + ", principal='" + principal + "'"
+                + ", host='" + host + "'"
+                + ", operation=" + operation
+                + ", permissionType=" + permissionType
+                + ")";
+        }
+        
+        public short errorCode() {
+            return this.errorCode;
+        }
+        
+        public String errorMessage() {
+            return this.errorMessage;
+        }
+        
+        public byte resourceType() {
+            return this.resourceType;
+        }
+        
+        public String resourceName() {
+            return this.resourceName;
+        }
+        
+        public byte patternType() {
+            return this.patternType;
+        }
+        
+        public String principal() {
+            return this.principal;
+        }
+        
+        public String host() {
+            return this.host;
+        }
+        
+        public byte operation() {
+            return this.operation;
+        }
+        
+        public byte permissionType() {
+            return this.permissionType;
+        }
+        
+        public DeleteAclsMatchingAcl setErrorCode(short v) {
+            this.errorCode = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setErrorMessage(String v) {
+            this.errorMessage = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setResourceType(byte v) {
+            this.resourceType = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setResourceName(String v) {
+            this.resourceName = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setPatternType(byte v) {
+            this.patternType = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setPrincipal(String v) {
+            this.principal = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setHost(String v) {
+            this.host = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setOperation(byte v) {
+            this.operation = v;
+            return this;
+        }
+        
+        public DeleteAclsMatchingAcl setPermissionType(byte v) {
+            this.permissionType = v;
+            return this;
+        }
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsRequestData.java b/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsRequestData.java
new file mode 100644
index 0000000..cfe1d71
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsRequestData.java
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
+
+package org.apache.kafka.common.message;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.kafka.common.protocol.ApiMessage;
+import org.apache.kafka.common.protocol.MessageUtil;
+import org.apache.kafka.common.protocol.Readable;
+import org.apache.kafka.common.protocol.Writable;
+import org.apache.kafka.common.protocol.types.ArrayOf;
+import org.apache.kafka.common.protocol.types.Field;
+import org.apache.kafka.common.protocol.types.Schema;
+import org.apache.kafka.common.protocol.types.Struct;
+import org.apache.kafka.common.protocol.types.Type;
+
+
+public class DeleteGroupsRequestData implements ApiMessage {
+    private List<String> groupsNames;
+    
+    public static final Schema SCHEMA_0 =
+        new Schema(
+            new Field("groups_names", new ArrayOf(Type.STRING), "The group names to delete.")
+        );
+    
+    public static final Schema SCHEMA_1 = SCHEMA_0;
+    
+    public static final Schema[] SCHEMAS = new Schema[] {
+        SCHEMA_0,
+        SCHEMA_1
+    };
+    
+    public DeleteGroupsRequestData(Readable readable, short version) {
+        this.groupsNames = new ArrayList<String>();
+        read(readable, version);
+    }
+    
+    public DeleteGroupsRequestData(Struct struct, short version) {
+        this.groupsNames = new ArrayList<String>();
+        fromStruct(struct, version);
+    }
+    
+    public DeleteGroupsRequestData() {
+        this.groupsNames = new ArrayList<String>();
+    }
+    
+    @Override
+    public short apiKey() {
+        return 42;
+    }
+    
+    @Override
+    public short lowestSupportedVersion() {
+        return 0;
+    }
+    
+    @Override
+    public short highestSupportedVersion() {
+        return 1;
+    }
+    
+    @Override
+    public void read(Readable readable, short version) {
+        {
+            int arrayLength = readable.readInt();
+            if (arrayLength < 0) {
+                this.groupsNames.clear();
+            } else {
+                this.groupsNames.clear();
+                for (int i = 0; i < arrayLength; i++) {
+                    this.groupsNames.add(readable.readNullableString());
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void write(Writable writable, short version) {
+        writable.writeInt(groupsNames.size());
+        for (String element : groupsNames) {
+            writable.writeString(element);
+        }
+    }
+    
+    @Override
+    public void fromStruct(Struct struct, short version) {
+        {
+            Object[] nestedObjects = struct.getArray("groups_names");
+            this.groupsNames = new ArrayList<String>(nestedObjects.length);
+            for (Object nestedObject : nestedObjects) {
+                this.groupsNames.add((String) nestedObject);
+            }
+        }
+    }
+    
+    @Override
+    public Struct toStruct(short version) {
+        Struct struct = new Struct(SCHEMAS[version]);
+        {
+            String[] nestedObjects = new String[groupsNames.size()];
+            int i = 0;
+            for (String element : this.groupsNames) {
+                nestedObjects[i++] = element;
+            }
+            struct.set("groups_names", (Object[]) nestedObjects);
+        }
+        return struct;
+    }
+    
+    @Override
+    public int size(short version) {
+        int size = 0;
+        size += 4;
+        for (String element : groupsNames) {
+            size += 2;
+            size += MessageUtil.serializedUtf8Length(element);
+        }
+        return size;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DeleteGroupsRequestData)) return false;
+        DeleteGroupsRequestData other = (DeleteGroupsRequestData) obj;
+        if (this.groupsNames == null) {
+            if (other.groupsNames != null) return false;
+        } else {
+            if (!this.groupsNames.equals(other.groupsNames)) return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = 0;
+        hashCode = 31 * hashCode + (groupsNames == null ? 0 : groupsNames.hashCode());
+        return hashCode;
+    }
+    
+    @Override
+    public String toString() {
+        return "DeleteGroupsRequestData("
+            + "groupsNames=" + MessageUtil.deepToString(groupsNames.iterator())
+            + ")";
+    }
+    
+    public List<String> groupsNames() {
+        return this.groupsNames;
+    }
+    
+    public DeleteGroupsRequestData setGroupsNames(List<String> v) {
+        this.groupsNames = v;
+        return this;
+    }
+}
diff --git a/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsResponseData.java b/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsResponseData.java
new file mode 100644
index 0000000..bb5a91a
--- /dev/null
+++ b/clients/src/generated/java/org/apache/kafka/common/message/DeleteGroupsResponseData.java
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+
+// THIS CODE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
... 30010 lines suppressed ...