How to programmatically define a field of type yet-to-be fully defined in GraphQL-Java? - graphql

I am "playing" with graphql-java and the related kickstarter servlet, modifying it to build the schema programmatically based on the types I discover automatically. The documentation is (almost) there but is outdated in spots and references deprecated methods. My particular issue is that the GraphQLFieldDefinition.Builder has four variants of the type(...) method - three accepting various (other) builders and one accepting the GraphQLOutputType, none of which I may have. Furthermore, those that accept builder actually invoke the build() method on those builders so I am anxious to pass any of my "unfinished" type builders either. I thought of defining all types upfront with no fields at all, then add fields to them after that but if build() gets called on these at that point in time, even if they don't get into an unwanted state today I can see how a future update may demand at most a single build() invocation.
So the question is how does one declare a field to yet-undefined or not fully defined type? For example, an Employee's manager field being itself of the Employee type such as:
type Employee {
name: String!
manager: Employee
reports: [Employee!]
buddy: Employee
...
}

As I noted in my comments, instead of attempting to (directly) use the builder or the built type one should create an instance of GraphQLTypeReference instead like so:
GraphQLTypeReference.typeRef(typeName)
This will be resolved automatically when the schema is built.
Should we want to indicate that this is not nullable even if the referenced type is, we further need to wrap into a GraphQLNonNull wrapper like so:
GraphQLNonNull.nonNull(typeRef)
... and use that as the type.

Related

Why is TYPE_ADDED_TO_INTERFACE considered a breaking change?

I am using the Apollo Server implementation of GraphQL, together with the Apollo Engine, and specifically the functionality to check whether a schema diff contains any breaking changes. I'd like to understand better why TYPE_ADDED_TO_INTERFACE is considered to be a breaking change, and if anyone can provide an example of a graphql query that would break, as a consequence?
I'm using the apollo/2.9.0 darwin-x64 node-v10.10.0 to perform the schema check with the apollo service:check command.
For example, if I have this schema:
interface Animal {
id: ID
}
type Dog implements Animal {
id: ID
favoriteToy: String
}
And then add this to the schema:
type Cat implements Animal {
id: ID
}
This is considered a breaking change. Why?
I can see that if someone is making a query for all the Animal objects, and has a ... on Dog fragment in the query, they would start getting Cat objects back with only the interface fields, until they also add a ... on Cat fragment. Is that what's considered breaking?
Having a type implement an interface it previously did not should not break existing queries. To your point, even if the inline fragment is omitted, the results will still be valid (they could result in an empty object being returned if no interface fields were selected, but that's still a valid response).
I could, however, foresee issues in specific clients resulting from this kind of change. For example, when using Apollo client, we often create an IntrospectionFragmentMatcher to specifically help the client correctly cache results from union or interface fields.
To support result validation and accurate fragment matching on unions and interfaces, a special fragment matcher called the IntrospectionFragmentMatcher can be used. If there are any changes related to union or interface types in your schema, you will have to update the fragment matcher accordingly.
In other words, having the schema change in this way could break client caching behavior. I suspect for clients that do schema-based code-generation, like apollo-android, this could also result in some runtime weirdness.

Read null as empty set in springdata-cassandra

I use spring-data-cassandra, and have entity like this:
#Table("users")
public class User {
#Column("permissions")
#CassandraType(type = DataType.Name.SET, typeArguments = {DataType.Name.TEXT})
public Set<String> permissions = new HashSet<>();
}
In cassandra I have table users with field permissions of type Set. It works fine when I store some values in the set, but when I try to store empty set, it becomes null when I read such entity from the repository.
Is there a way to force spring-data-cassandra to change null to empty HashSet? Or can I somehow add custom reader for this specific property of the entity?
TL;DR;
That's Cassandra's default behavior to return null for empty Collection and Map-typed columns.
Further Read
Cassandra returns null values for lists, sets, and maps, which do not contain any items. This is especially unfortunate when using classes with pre-initialized fields as seen in your question. There's an open ticket (DATACASS-266 - Loading empty collection-typed properties overwrites pre-initialized fields) in the issue tracker - as of now, without comments or votes.
We're not exactly sure whether it's a good idea to skip setting properties or apply some sort of defaulting when dealing with empty (null) collections as this raises follow-up questions what to do when:
Creating an instance through constructor creation: A value is required in such case. For property access, we could omit to set the property, for constructor creation we must provide a value.
The pre-initialized collection contains items but the one received from Cassandra is null.
We assume, the change would be applied, what will happen with already existing code that assumes empty collections default to null.
A possibility to address this behavior could be configuration on MappingCassandraConverter or an extension point to override so users can apply their own empty collection behavior.
I've been trying to eliminate the null collections in my model objects as well, and while it may not be possible to do that at the Spring Data level currently (version 2.1.x), there are some options you can consider:
Use property access for the field in question (i.e. use the annotation #AccessType(PROPERTY)), and in the setter method, set the field to an empty collection when the argument is null.
Define a compatible (see below) constructor that sets the field to an empty collection when a null is provided (and if the model is mutable, you may still want to provide the setter as above).
There are some caveats to ensure Spring Data Cassandra uses the desired constructor (e.g. don't provide a no argument constructor), so it's critical to review the "Object Mapping Fundamentals" section of the reference guide (https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#mapping.fundamentals).
Among the recommendations in that reference guide (as of version 2.1 at least) is to use an all argument constructor and make model objects immutable, which would work well with the constructor-based approach to handling nulls. Though it does mean writing and maintaining the constructor to handle the nulls rather than relying on Lombok's #AllArgsConstructor.
I have used the property access approach in one case, but not the constructor approach. However I do intend go the constructor route when adding new or model classes (I'm a fan of immutable objects, and will explore that route even without any collection fields)
I believe Spring Data Cassandra 2.0 also added persistence lifecycle callbacks which is another possible option I suppose, but I ruled that out, mainly because the logic would not reside in the model class itself (as well as going against the recommendations from the creators of the framework)

Is there a reason why the default modelbinder doesn't bind to fields?

I'm using ASP.NET MVC3 and i'm wondering that the default modelbinder binds to public properties but not to public fields.
Normally i just define the model classes with properties but sometimes i use some predefined classes which contains some fields. And everytime i have to debug and remember that the modelbinder just don't like fields.
The question: Whats the reason behind it?
but sometimes i use some predefined classes which contains some fields
While I cannot answer your question about the exact reason why the default model binder works only with properties (my guess is that it respects better encapsulation this way and avoids modifying internal state of the object which is what fields represent) I can say that what you call predefined classes should normally be view models. You should always use view models to and from your controller actions. Those view models are classes that are specifically defined to meet the requirements of the given view.
So back to the main point: fields are supposed to be modified only from within the given class. They should not be accessed directly from the outside. They represent and hold internal state of the class. Properties on the other hand is what should be exposed to the outside world. Imagine that in the property getter/setter you had some custom logic. By modifying directly the field this custom logic would be broken and potentially bring the object into an inconsistent state.
Maybe the reason for ignoring fields is to increase performance of the binder. Instead of searching all the Fields and properties. The Model Binder search for Properties only.
Though I think the Model Binder use cache to improve performance.
DefaultModelBinder exposes a public method:
DefaultModelBinder.BindModel, and a number of protected method available for overriding. All of them listed here.
Besides the model, these method refer to properties only, not fields, like
GetModelProperties,
GetFilteredModelProperties,
GetPropertyValue,
OnXYZValidating,
OnXYZValidated,
OnXYZUpdating,
OnXYZUpdated,
GetXYZValue,
where XYZ stands for either Model, or Property/ies, or both, and so on.
As you can see there is no Fields mentioned with these names whatsoever. As Darin explained no direct changes to Model's state are tolerated by the Binder. Hence no Field in its methods.
And also, you may wish to take a look at another important class: ModelBindingContext. An instance of this class gets passed to the BindModel, and subsequently to BindSimpleModel, and BindComplexModel, depending on model type (string, int,... are considered simple, everything else is complex).
So, this context has the following properties:
ModelXYZ, and
PropertyXYZ.
In other words you have no means to reference the fields in your ViewModel unless you do not override these classes and undertake special actions to do so.
But again, beware of fighting the framework, its always easier to follow it instead.
EDIT: The ModelMetadata class holds all the data needed to bind the model. Its code however, shows no sign of fields, field names, etc. Only properties are referenced and accessed. So, even if you try to inherit and override DefaultModelBinder and ModelBinderContext, you still won't be able to access fiellds, nevermind what their access modifier is: public, private, etc.
Hope this explains most of it.

Registering all types in Assembly for Unity

I'm working on a large Asp.Net MVC3 application (>50 views) and we are currently planning on using Unity for our dependency injection framework. For ease of maintenance, I would like to be able to query the assembly to find all of the base types, then register them with Unity.
Based on sample code from the Unity MVC3 Project for registering all controllers, I tried the following code -
var orchestratorTypes = (from t in Assembly.GetCallingAssembly().GetTypes()
where typeof(IOrchesratorBase).IsAssignableFrom(t) &&
!t.IsAbstract
select t).ToList();
orchestratorTypes.ForEach(t => container.RegisterType(t);
When I run the application I get the following error message
The current type, WwpMvcHelpers.BaseClasses.IOrchesratorBase, is an interface and cannot be constructed. Are you missing a type mapping?
If I register the class using individually, as below -
container.RegisterType<IOrchesratorBase, HomeOrchestrator>();
Everything works correctly. Is there a way to do this so that I don't have to register each type individually?
EDIT
Per request, my inheritance hierarchy is
HomeOrcestrator <- IOrchesratorBaseList<LocalModel>
<- OrchesratorBase<LocalModel> <- IOrchesratorBase
The usage in the controller is
public class HomeController : ControllerListBase <HomeOrchestrator, LocalModel>
{
public HomeController() {}
public HomeController(IOrchesratorBase homeOrchestrator) {
this.Orchestrator = (HomeOrchestrator) homeOrchestrator;
}
The LINQ to get the types appears to work. I don't think that's your problem.
You'll get a similar error if you just write
container.RegisterType(typeof(HomeOrchestrator));
and call container.Resolve<IOrchesratorBase>().
In other words, RegisterType(t) is not the same as RegisterType<I, T>().
The real question is, what are you resolving and how do you want it resolved? Your query is finding implementors of IOrchesratorBase. Are your injection constructor parameters of that type? If so, what's Unity supposed to do when 20 types implement that interface?
Can you provide more information on your class/interface hierarchy, constructor parameters, and what you expect/want to happen?
(I'd refactor to change IOrchesratorBase to IOrchestratorBase, BTW.) :)
Edit
Based on the edited question, the problem is that, in order to resolve a HomeController, Unity is looking for a type registration for IOrchesratorBase. It determines the interface type by the parameter types of the constructor with the most parameters.
If you write container.RegisterType<IOrchesratorBase, HomeOrchestrator>() the answer is obvious - Unity will construct an instance of HomeOrchestrator and inject it.
Now, is there more than one type that implements IOrchesratorBase? If so, and you register both of them (explicitly), Unity will use whichever one you register last. That may not be what you want.
If you have multiple controllers, each taking a different interface type in their constructors (with only one implementation per interface), you'll need to figure out what each interface type is and re-run your LINQ registration for each one. That could be done via reflection - find the orchestrators or the controllers.
If you have multiple controllers, each taking the same interface type in their constructors and you want different implementations for each, you've got a problem. You'd have to register named types and determine the names somehow, or something similar.
Unity isn't magic. It can't figure out your intentions.
Addendum
Unity can operate in a convention-over-configuration mode; see Using Unity With Minimal Configuration.

Is there anyway to declare a TYPE without a Property in Oracle 10gR2

I want to create a base object that has only methods. The object would be QUEUABLE_OBJECT_TYPE and it will have an ENQUEUE method(s). The Payload of these messages (properties) would be added by subtyping this object.
I get an error that makes it sound like you cannot:
PLS-00589: no attributes found in object type "QUEUABLE_OBJECT_TYPE"
Does anyone know a way around this error? Or is it possible in the subtypes to hide this property of the supertype?
Either would be an acceptable answer.
Everything I've read suggests it is not possible to create a type without any attributes. Nor is it possible to hide a dummy attribute in a subtype. You may simply have to have an attribute in the master type, and utilise it - e.g. by making it identify the version of the type.
Oracle does provide some generic types, see documentation for details

Resources