-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
332 comsngularkloadgenserializerprotobufserializer nullpointerexception #355
Merged
dhergonsngular
merged 16 commits into
master
from
332-comsngularkloadgenserializerprotobufserializer-nullpointerexception
Mar 28, 2023
Merged
Changes from 13 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
b21e311
#332 Add Files Modified To Solve Exception
AdrianLagartera 9a197c7
#332 Add get dependencies and build proto.
jemacineiras af0dfe3
#332 Add Test And Documentation
AdrianLagartera a129cd7
#332 Add Topic Name Strategy
AdrianLagartera 3f5d91c
Merge branch 'master' into 332-comsngularkloadgenserializerprotobufse…
AdrianLagartera b8426a9
#332 Change image from kafka manager to newest version
AdrianLagartera 4858372
Get the schema name from the schema references of imported classes
alfredo9f 0fd3920
#332 Removed generator set up by TopicNameStrategy
dhergonsngular dd531d8
#332 refactor
dhergonsngular 43ed7da
Merge remote-tracking branch 'origin/master' into 332-comsngularkload…
dhergonsngular b037bdf
#332 refactor
dhergonsngular 82a445c
#332 refactor
dhergonsngular 622398a
#332 updated pom version
dhergonsngular eb5f8b9
#332 fixes PR
dhergonsngular e86011b
#332 fixes PR
dhergonsngular 5fa0649
update pom
alfredo9f File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
|
||
<artifactId>kloadgen</artifactId> | ||
|
||
<version>5.4.1</version> | ||
<version>5.4.2</version> | ||
|
||
<name>KLoadGen</name> | ||
<description>Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial | ||
|
@@ -235,6 +235,17 @@ | |
</roles> | ||
<timezone>Europe/Madrid</timezone> | ||
</developer> | ||
<developer> | ||
<id>alfredo9f</id> | ||
<name>Alfredo González</name> | ||
<email>[email protected]</email> | ||
<organization>Sngular</organization> | ||
<organizationUrl>https://www.sngular.com</organizationUrl> | ||
<roles> | ||
<role>Senior Backend Developer</role> | ||
</roles> | ||
<timezone>Europe/Madrid</timezone> | ||
</developer> | ||
</developers> | ||
|
||
<scm> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,16 +25,21 @@ | |
import com.google.protobuf.Descriptors; | ||
import com.google.protobuf.Descriptors.DescriptorValidationException; | ||
import com.sngular.kloadgen.model.FieldValueMapping; | ||
import com.sngular.kloadgen.util.JMeterHelper; | ||
import com.sngular.kloadgen.util.ProtobufHelper; | ||
import com.squareup.wire.schema.internal.parser.EnumElement; | ||
import com.squareup.wire.schema.internal.parser.FieldElement; | ||
import com.squareup.wire.schema.internal.parser.MessageElement; | ||
import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
import com.squareup.wire.schema.internal.parser.TypeElement; | ||
import io.confluent.kafka.schemaregistry.client.SchemaMetadata; | ||
import io.confluent.kafka.schemaregistry.client.rest.entities.SchemaReference; | ||
import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.apache.commons.collections4.Predicate; | ||
import org.apache.commons.lang3.RandomUtils; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.apache.jmeter.threads.JMeterContextService; | ||
|
||
public class SchemaProcessorUtils { | ||
|
||
|
@@ -142,11 +147,11 @@ public static String[] splitAndNormalizeFullFieldName(final String fullFieldName | |
return Arrays.stream(fields).map(field -> field.replaceAll("\\[.*]", "")).toArray(String[]::new); | ||
} | ||
|
||
public static Descriptors.Descriptor buildProtoDescriptor(final ProtoFileElement schema) throws Descriptors.DescriptorValidationException, IOException { | ||
public static Descriptors.Descriptor buildProtoDescriptor(final ProtoFileElement schema, final Object metadata) throws Descriptors.DescriptorValidationException, IOException { | ||
|
||
final DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder(); | ||
final List<String> imports = schema.getImports(); | ||
for (String importedClass : imports) { | ||
for (final String importedClass : imports) { | ||
try (final InputStream resourceStream = SchemaProcessorUtils.class.getClassLoader().getResourceAsStream(importedClass)) { | ||
if (null != resourceStream) { | ||
final String schemaToString = new String(resourceStream.readAllBytes()); | ||
|
@@ -156,6 +161,12 @@ public static Descriptors.Descriptor buildProtoDescriptor(final ProtoFileElement | |
schemaBuilder.addDependency(importedSchema.getFileDescriptorSet().getFile(0).getName()); | ||
schemaBuilder.addSchema(importedSchema); | ||
} | ||
} else { | ||
final var importSchema = JMeterHelper.getParsedSchema(getSubjectName(importedClass, metadata), JMeterContextService.getContext().getProperties()); | ||
if (!ProtobufHelper.NOT_ACCEPTED_IMPORTS.contains(importedClass)) { | ||
schemaBuilder.addDependency(((ProtobufSchema) importSchema).toDescriptor().getFullName()); | ||
schemaBuilder.addSchema(convertDynamicSchema((ProtobufSchema) importSchema)); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -173,6 +184,24 @@ public static Descriptors.Descriptor buildProtoDescriptor(final ProtoFileElement | |
return schemaBuilder.build().getMessageDescriptor(messageElement.getName()); | ||
} | ||
|
||
private static String getSubjectName(final String importedClass, final Object metadata) { | ||
final List<SchemaReference> references = ((SchemaMetadata) metadata).getReferences(); | ||
String subjectName = null; | ||
|
||
for (final SchemaReference schemaReference : references) { | ||
if (schemaReference.getName().equals(importedClass)) { | ||
subjectName = schemaReference.getSubject(); | ||
break; | ||
} | ||
} | ||
|
||
return Objects.requireNonNullElse(subjectName, importedClass); | ||
} | ||
|
||
private static DynamicSchema convertDynamicSchema(final ProtobufSchema importSchema) throws DescriptorValidationException { | ||
return processImported(Arrays.asList(importSchema.rawSchema().toSchema().split("\\n"))); | ||
} | ||
|
||
private static Predicate<String> isValid() { | ||
return line -> !line.contains("//") && !line.isEmpty(); | ||
} | ||
|
@@ -184,7 +213,7 @@ private static DynamicSchema processImported(final List<String> importedLines) t | |
String packageName = ""; | ||
final var linesIterator = importedLines.listIterator(); | ||
while (linesIterator.hasNext()) { | ||
final var fileLine = linesIterator.next(); | ||
final var fileLine = linesIterator.next().trim(); | ||
|
||
if (fileLine.startsWith("package")) { | ||
packageName = StringUtils.chop(fileLine.substring(7).trim()); | ||
|
@@ -211,9 +240,11 @@ private static MessageDefinition buildMessage(final String messageName, final Li | |
while (messageLines.hasNext() && !exit) { | ||
final var field = messageLines.next().trim().split("\\s"); | ||
if (ProtobufHelper.isValidType(field[0])) { | ||
messageDefinition.addField(OPTIONAL, field[0], field[1], Integer.parseInt(checkIfChoppable(field[3]))); | ||
messageDefinition.addField(OPTIONAL, field[0], field[1], Integer.parseInt(checkIfGreppable(field[3]))); | ||
} else if (ProtobufHelper.LABEL.contains(field[0])) { | ||
messageDefinition.addField(field[0], field[1], field[2], Integer.parseInt(checkIfChoppable(field[4]))); | ||
messageDefinition.addField(field[0], field[1], field[2], Integer.parseInt(checkIfGreppable(field[4]))); | ||
} else if ("message".equalsIgnoreCase(field[0])) { | ||
messageDefinition.addMessageDefinition(buildMessage(field[1], messageLines)); | ||
} else if ("}".equalsIgnoreCase(field[0])) { | ||
exit = true; | ||
} | ||
|
@@ -222,7 +253,7 @@ private static MessageDefinition buildMessage(final String messageName, final Li | |
return messageDefinition.build(); | ||
} | ||
|
||
private static String checkIfChoppable(final String field) { | ||
private static String checkIfGreppable(final String field) { | ||
String choppedField = field; | ||
if (field.endsWith(";")) { | ||
choppedField = StringUtils.chop(field); | ||
|
@@ -231,8 +262,8 @@ private static String checkIfChoppable(final String field) { | |
} | ||
|
||
private static MessageDefinition buildProtoMessageDefinition( | ||
final String fieldName, final TypeElement messageElement, final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, | ||
final int previousDeepLevel) { | ||
final String fieldName, final TypeElement messageElement, final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, | ||
final int previousDeepLevel) { | ||
|
||
final int nextDeepLevel = previousDeepLevel + 1; | ||
|
||
|
@@ -241,20 +272,20 @@ private static MessageDefinition buildProtoMessageDefinition( | |
final MessageDefinition.Builder msgDef = MessageDefinition.newBuilder(fieldName); | ||
final var element = (MessageElement) messageElement; | ||
extracted(globalNestedTypesByLevelAndMessage, msgDef, element.getFields(), nextDeepLevel, fieldName); | ||
for (var optionalField : element.getOneOfs()) { | ||
for (final var optionalField : element.getOneOfs()) { | ||
extracted(globalNestedTypesByLevelAndMessage, msgDef, optionalField.getFields(), nextDeepLevel, fieldName); | ||
} | ||
return msgDef.build(); | ||
} | ||
|
||
private static void extracted( | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final Builder msgDef, final List<FieldElement> fieldElementList, | ||
final int deepLevel, final String messageName) { | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final Builder msgDef, final List<FieldElement> fieldElementList, | ||
final int deepLevel, final String messageName) { | ||
|
||
final HashMap<String, TypeElement> nestedTypes = processLevelTypes(globalNestedTypesByLevelAndMessage, msgDef, fieldElementList, deepLevel, | ||
messageName); | ||
messageName); | ||
5uso-sng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
for (var elementField : fieldElementList) { | ||
for (final var elementField : fieldElementList) { | ||
final var elementFieldType = elementField.getType(); | ||
final var dotType = checkDotType(elementFieldType); | ||
if (nestedTypes.containsKey(elementFieldType)) { | ||
|
@@ -295,7 +326,7 @@ private static void extracted( | |
msgDef.addField("repeated", "typemapnumber" + elementField.getName(), elementField.getName(), elementField.getTag()); | ||
|
||
msgDef.addMessageDefinition( | ||
MessageDefinition.newBuilder("typemapnumber" + elementField.getName()).addField(OPTIONAL, "string", "key", 1).addField(OPTIONAL, realType, "value", 2).build()); | ||
MessageDefinition.newBuilder("typemapnumber" + elementField.getName()).addField(OPTIONAL, "string", "key", 1).addField(OPTIONAL, realType, "value", 2).build()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You use the value of "typemapnumber" several times, so it would be nice to create a variable with that value. |
||
} else if (Objects.nonNull(elementField.getLabel())) { | ||
msgDef.addField(elementField.getLabel().toString().toLowerCase(), elementField.getType(), elementField.getName(), elementField.getTag()); | ||
} else { | ||
|
@@ -305,9 +336,9 @@ private static void extracted( | |
} | ||
|
||
private static HashMap<String, TypeElement> processLevelTypes( | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final Builder msgDef, final List<FieldElement> fieldElementList, | ||
final int deepLevel, | ||
final String messageName) { | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final Builder msgDef, final List<FieldElement> fieldElementList, | ||
final int deepLevel, | ||
final String messageName) { | ||
|
||
final List<String> allTypesInstantiatedByAttributesWithSimpleNames = new ArrayList<>(); | ||
for (final FieldElement fieldElement : fieldElementList) { | ||
|
@@ -340,13 +371,13 @@ private static HashMap<String, TypeElement> processLevelTypes( | |
} | ||
|
||
private static void addDefinition( | ||
final MessageDefinition.Builder msgDef, final String typeName, final TypeElement typeElement, | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final int deepLevel) { | ||
final MessageDefinition.Builder msgDef, final String typeName, final TypeElement typeElement, | ||
final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, final int deepLevel) { | ||
|
||
if (typeElement instanceof EnumElement) { | ||
final var enumElement = (EnumElement) typeElement; | ||
final EnumDefinition.Builder builder = EnumDefinition.newBuilder(enumElement.getName()); | ||
for (var constant : enumElement.getConstants()) { | ||
for (final var constant : enumElement.getConstants()) { | ||
builder.addValue(constant.getName(), constant.getTag()); | ||
} | ||
msgDef.addEnumDefinition(builder.build()); | ||
|
@@ -358,8 +389,8 @@ private static void addDefinition( | |
} | ||
|
||
private static void fillNestedTypes( | ||
final TypeElement messageElement, final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, | ||
final int deepLevel) { | ||
final TypeElement messageElement, final HashMap<Integer, HashMap<String, HashMap<String, TypeElement>>> globalNestedTypesByLevelAndMessage, | ||
final int deepLevel) { | ||
|
||
HashMap<String, HashMap<String, TypeElement>> messageNestedTypes = globalNestedTypesByLevelAndMessage.get(deepLevel); | ||
if (messageNestedTypes == null) { | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not an error, but I think it would be cleaner to create a variable to hold the value of importSchema because that way you avoid to do the cast several times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed