Resolve by ID interface Graphql federation (Apollo) - graphql

I am trying to resolve an interface by ID with netflix-dgs and Apollo federation. But the DgsEntityFetcher does not seem to be registered for interfaces.
I also tried declaring entity resolvers for types B and C and still null result.
Here is a sample:
interface A #key(fields:"id"){
id: ID!
...
}
type B implements A {...}
type C implements A {...}
//This type can appear in multiple services/subgraphs
type SomeObject #key(fields:"id"){
id: ID!
aTypeField: A #provides(fields: "id")
}

Related

SPRING JPA: Is there an option to only connect the primary key of the other entity?

Question is that if there is an option to represent the parent entity primary key on the child entity without the whole entity?
Class Parent {
val id: Int,
val name: String
}
Class Child {
val id: Int,
val name: String,
val parentId: Int // this would be the goal
}
I'm aware that if connect the parent with #OneToOne as private property it would work or if i would simply use the parent entity with correct relation without cascade types given.
a possible solution for the questions

SpringBoot GraphQL mutation giving error No Root resolvers for query type 'Query' found

Am getting the error No Root resolvers for query type 'Query' found when using mutation in SpringBoot with GraphQL. The queries are working fine , but on adding the GraphQLMutationResolver, it is giving the error on Spring Boot startup.
Kindly advise.
.graphqls file
type Query {
allBooks: [Book]
getBookByIsn(isn: Int): Book
allPublishers: [Publisher]
}
type Book {
isn: Int
title: String
author: String
publishedDate: String
publisher: Publisher!
}
type Publisher {
pId : Int
publisherName: String
address: String
}
input CreatePublisher {
pId : Int
publisherName: String
address: String
}
type Mutation {
addPublisher(input: CreatePublisher!): Publisher
}
Mutation Resolver
#Component
public class PublisherMutation implements GraphQLMutationResolver{
#Autowired
private PublisherRepository publisherRepository;
#Transactional
public Publisher addPublisher(CreatePublisher createPublisher ) {
Publisher publisher = new Publisher(createPublisher.getPId(), createPublisher.getPublisherName(), createPublisher.getAddress());
publisherRepository.save(publisher);
return publisher;
}
}
Done, solved by adding a newTypeWiring of type Mutation for Create

Why is Spring Data MongoDB insert/save operation not returning the ObjectId

I have tried this several ways (U can assume my MongoConfiguration is Correct)
Using implementation 'org.springframework.boot:spring-boot-starter-data-mongodb:2.5.3'
My Class
#Document(collection = "address")
class Address {
#Id
var id: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
...
My Repository
#Repository
interface AddressRepository : MongoRepository<Address, String> {
fun findByLabel(label: String): Address
}
in My #RestController I call the save (or insert)
val savedAddress = addressRepository.insert(address)
According to Gradle: org.springframework.data:spring-data-mongodb:3.1.6 as well as Gradle: org.springframework.data:spring-data-commons:2.4.6 Docs
Returns: the saved entity; will never be null.
However It does create a record! I inspected the result by using Compass
But it only echoes the address content I used to create it! witout the ID
If I would query the record e.g.
returnedAddress= savedAddress.label?.let { addressRepository.findByLabel(it) }!!
I get the rocord returned WITH the Id!
This Behavior I detected some time now and it is not always possible to locate the correct record again if the Id is the only Unique key in the collection!
Is there a Mistake?, configuration or any other way I can get the ObjectId / _id emmitted properly
Note: <S extends T> S save(S entity) calls insert when the entity record is new

Advantages of interface implements in GraphQL

I'm new to GraphQL.
// using interface
interface User {
name: String
}
type UserDetail implements User {
name: String
email: String
}
// just type
type User {
name: String
}
type UserDetail {
name: String
email: String
}
There is duplicated field name in interface User and type UserDetail.
I thought UserDetail doesn't have to include name.
I couldn't find detailed information of interface.
Why do I use interface, implements instead of just type?
And I want to know differences of using interface and type, advantages of using interface.
Please comment any advices.

SpringBoot GraphQL field name mismatch

It seems that the names defined in the .graphqls file MUST match the field names in the POJO. Is there a way to maybe annotate the field so that they don't have to?
For example, I have something like this in the graphqls file
type Person {
personId: ID!
name: String!
}
Then in my Entity POJO I have like
#Id
#Column(name="PERSON_ID")
#JsonProperty("person_id")
private int personId;
#Column(name="NAME")
#JsonProperty("name")
private String name;
So, the intention is for the field name to be personId and the database to store it as a column called PERSON_ID and for it to get serialized as JSON and GraphQL as person_id
But graphql talks in the language of the schema. So it serializes it as personId which matches the schema field but is not the intention. I could change the schema to be person_id but then I need to change the field too... This isn't the end of the world but it's quite "un-javalike" to have fields named that way.
I am using this library:
compile group: 'com.graphql-java', name: 'graphql-spring-boot-starter', version: '5.0.2'
I have also seen the #GraphQLName annotation in the annotations library but I must be missing something because it doesn't do what I am expecting or maybe I am using it wrong.
Is there some way to get around this or should I just change the names?
GraphQL Java uses PropertyDataFetcher by default to resolve field values (see data fetching section in the docs). This data fetcher works out-of-the box when the data object returned by a top level field data fetcher contains child fields that match the data object property names.
However, you can define your own data fetcher for any field and use whatever rule you need.
So, if you want a schema that looks like this
type Person {
person_id: ID!
name: String!
}
and your entity like this:
class Person {
private int personId;
private String name;
// getters and setters
}
You can write a simple custom data fetcher for the field personId
private RuntimeWiring buildWiring() {
return RuntimeWiring.newRuntimeWiring()
// query root data fetchers wiring
.type(newTypeWiring("Person")
.dataFetcher("person_id", environment -> {
Person person = environment.getSource();
return person.getPersonId();
})
)
// maybe other wirings
.build();
}

Resources