Unlike GraphQLProperty, GraphQLVariable(s) isn't class level -- I'm not sure how I'm suppose to use them to achieve my query/mutation.
I'm trying to build the following mutation
mutation Create2FA($inputDescriptor: Input2FA!) {
Create2FA(inputDescriptor: $inputDescriptor) {
TwoFAID
Description
...
}
}
Or A more general usage example for Queries:
query FindProducts($filter: InputFilter!) {
FindProductsWithFilter(filter: $filter) {
SKU
Description
}
}
Expected Uses
I was anticipating a model definition like (but illegal to put variables @ class level):
@GraphQLProperty(name = "Create2FA")
@GraphQLVariables({
@GraphQLVariable(name = "TwoFA", scalar = "CreateTwoFA!")
})
public class MutationCreate2FA extends TwoFAModel {
}
Available Uses
These are my (legal) options but all provide the wrong result.
Test Case
package privoro.aid.authenticator.graphql;
import io.aexp.nodes.graphql.GraphQLRequestEntity;
import io.aexp.nodes.graphql.Variable;
import org.junit.Test;
import org.privoro.aid.authenticator.graphql.InputCreate2FA;
import org.privoro.aid.authenticator.graphql.MutationCreate2FA;
import java.net.MalformedURLException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
public class TestGraphQLRequestEntity {
private String EXAMPLE_URL = "https://graphql.example.com";
@Test
public void mutationWithVariables() throws MalformedURLException {
InputCreate2FA input = new InputCreate2FA();
input.setUserID("user-id");
input.setDeviceID("device-id");
input.setRelyingPartyID("relying-party-id");
input.setDescription("description");
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
.url(EXAMPLE_URL)
.variables(new Variable<InputCreate2FA>("TwoFA", input))
.request(MutationCreate2FA.class)
.build();
System.out.println("Request Entity:" + requestEntity.toString());
assertThat(requestEntity.toString(), containsString("'query ($TwoFA: CreateTwoFA!) { Create2FA (TwoFA: $TwoFA) {"));
}
}
Input variable model
package org.privoro.aid.authenticator.graphql;
public class InputCreate2FA {
public String UserID;
public String RelyingPartyID;
public String Description;
public String DeviceID;
}
Result Model
package org.privoro.aid.authenticator.graphql;
public class TwoFA {
public String UserID;
public String RelyingPartyID;
public String Description;
public String Status;
public String Reason;
public String CreatedTimestamp;
public String ExpiresAt;
public String TwoFAID;
}
1 Property and Values set inside the class on the result model property
MutationCreate2FA
public class MutationCreate2FA {
@GraphQLProperty(name = "Create2FA")
@GraphQLVariables({
@GraphQLVariable(name = "TwoFA", scalar = "CreateTwoFA!")
})
public TwoFAModel twoFa;
}
Output:
query ($TwoFA:CreateTwoFA!){ twoFA : Create2FA(TwoFA:$TwoFA) { Status RelyingPartyID Description CreatedTimestamp UserID TwoFAID ExpiresAt Reason } }
2 Property on the class but variables on a result model property
MutationCreate2FA
@GraphQLProperty(name = "Create2FA")
public class MutationCreate2FA {
@GraphQLVariables({
@GraphQLVariable(name = "TwoFA", scalar = "CreateTwoFA!")
})
public TwoFAModel twoFa;
}
Output:
query ($TwoFA:CreateTwoFA!){ Create2FA { twoFA (TwoFA:$TwoFA) { Status RelyingPartyID Description CreatedTimestamp UserID TwoFAID ExpiresAt Reason } } }
3 Variables only specified when building request
MutationCreate2FA
@GraphQLProperty(name = "Create2FA", arguments = {
@GraphQLArgument(name = "TwoFA", value = "$TwoFA")
})
public class MutationCreate2FA extends TwoFA {
}
Output (close, but the builder doesn't inject the variables):
query { Create2FA (TwoFA:$TwoFA) { Status RelyingPartyID Description CreatedTimestamp UserID TwoFAID ExpiresAt Reason } }
Preferred usage
If I step back from the docs a little and imagine how I might specify query's and mutations with variables I come up with:
@GraphQLOperation(name = "Create2FAMutation", type="mutation", variables = {
@GraphQLVariable(name = "inputCreate2FA", scalar = "Create2FA!")
}, properties = {
@GraphQLProperty(name = "Create2FA", arguments = {
@GraphQLArgument(name = "TwoFA", variable = "inputCreate2FA")
})
})
class MutationCreate2FA extends TwoFA {
}
Output
mutation Create2FAMutation ($inputCreate2FA: Create2FA!) { Create2FA (TwoFA:$inputCreate2FA) { Status RelyingPartyID Description CreatedTimestamp UserID TwoFAID ExpiresAt Reason } }
I think this preferred usage can be provided and be backwards compatible w/ current usage.
I've introduced an annotation @GraphQLOperation which is optional (if you don't need variables) in your query/mutation. This would remove the need for @GraphQLVariables (altogether) and @GraphQLVariable would only be used in top level operation annotations (not on models or on model properties).
I've also added an optional variable parameter to the @GraphQLArgument which associates the argument to a specified variable. The addition allows properties to be defined as arguments that can be bound to variables later which reduces unwanted coupling from the model to the operation.
Unlike GraphQLProperty, GraphQLVariable(s) isn't class level -- I'm not sure how I'm suppose to use them to achieve my query/mutation.
I'm trying to build the following mutation
Or A more general usage example for Queries:
Expected Uses
I was anticipating a model definition like (but illegal to put variables @ class level):
Available Uses
These are my (legal) options but all provide the wrong result.
Test Case
Input variable model
Result Model
1 Property and Values set inside the class on the result model property
MutationCreate2FA
Output:
2 Property on the class but variables on a result model property
MutationCreate2FA
Output:
3 Variables only specified when building request
MutationCreate2FA
Output (close, but the builder doesn't inject the variables):
Preferred usage
If I step back from the docs a little and imagine how I might specify query's and mutations with variables I come up with:
Output
I think this preferred usage can be provided and be backwards compatible w/ current usage.
I've introduced an annotation
@GraphQLOperationwhich is optional (if you don't need variables) in your query/mutation. This would remove the need for@GraphQLVariables(altogether) and@GraphQLVariablewould only be used in top level operation annotations (not on models or on model properties).I've also added an optional
variableparameter to the@GraphQLArgumentwhich associates the argument to a specified variable. The addition allows properties to be defined as arguments that can be bound to variables later which reduces unwanted coupling from the model to the operation.