Skip to content

Consider adding type parameters to AbstractTestElement so elements are linked with schemas #5967

@vlsi

Description

@vlsi

Use case

#5946 adds schemes in backward-compatible way, so TestElement implements default methods getSchema() = TestElementSchema and getProps() = ..., however it does not enforce constraints on the schemas.

With suggestion in 596, every element has to override two methods, and the second one has to be in every subclass otherwise getProps() will return base PropertiesAccessor<AbstractTestElement, AbstractTestElementSchema>, so extra properties won't be visible in autocomplete.

// Users need to override two methods with a concrete types
// Here's an example for AbstractThreadGroup

    @Override
    public AbstractThreadGroupSchema getSchema() {
        return AbstractThreadGroupSchema.INSTANCE;
    }

// The generics should be `? extends ..`, so subclasses can override with subtypes
    @Override
    public PropertiesAccessor<? extends AbstractThreadGroup, ? extends AbstractThreadGroupSchema> getProps() {
        return new PropertiesAccessor<>(this, getSchema());
    }

We can't add generics to TestElement, see #5946 (comment).

Possible solution

If we add generics to AbstractTestElement, then we could link elements with their schemas:

public abstract class AbstractTestElement<
        Schema extends TestElementSchema,
        TestElementClass extends AbstractTestElement<Schema, TestElementClass>>
        implements TestElement, Serializable, Searchable {
    private final PropertiesAccessor props = new PropertiesAccessor(this, getSchema());

    // If we add generics, then getProps could be implemented in a single place (in AbstractTestElement),
    // and the elements would inherit it, however, they would need to add type parameters
    public PropertiesAccessor<TestElementClass, Schema> getProps() {
        return props; // it is safe to reuse a single instance and "unsafe cast" is safe here
    }
...

public abstract class AbstractThreadGroup<
        Schema extends AbstractThreadGroupSchema,
        TestElementClass extends AbstractThreadGroup<Schema, TestElementClass>> 
        extends AbstractTestElement<Schema, TestElementClass>
    implements Serializable, Controller, JMeterThreadMonitor, TestCompilerHelper {

...

public class OpenModelThreadGroup :
    AbstractThreadGroup<OpenModelThreadGroupSchema, OpenModelThreadGroup>(),

However, adding generics to AbstractTestElement is likely a disruptive change. For instance, Kotlin does not support raw types, and if we add generics to AbstractTestElement, AbstractThreadGroup, and so on, then Kotlin users would have to change their code in order to compile with never JMeter versions. Even though it should not be a big deal, recursive generics are not easy.

Possible workarounds

No response

JMeter Version

5.5

Java Version

No response

OS Version

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions