1

I just started exploring graphql, so am running in to initial problems using the framework. The code used on this post is hosted on github @ https://github.com/samshers/graphQL-Starter
The graphql schema of my api is as below:

schema {
 query: Query
}

type Query {
 allCities: [City]
 city(name: String): City
 state(name: String): State 
}

type City {
    name: String
    population: String
    state: State
}

type State {
    name: String
    population: String
    country: Country
    cities : [City]
} 

type Country {
    name: String
    population: String
}

The query I am trying to execute is -

{
  city(name: "BayArea") {
    name
    population
    state {
        name
        population
        cities  {
            name
        }
        country {
            name
            population
        }
    }
  }
}

and the result I am getting is -

{
    "errors": [],
    "data": {
        "city": {
            "name": "BayArea",
            "population": "7200000",
            "state": {
                "name": "CA",
                "population": "39900000",
                "cities": [],
                "country": {
                    "name": "USA",
                    "population": "330000000"
                }
            }
        }
    },
    "extensions": null
}

The problem is with this part of the result -

"population": "39900000",
"cities": [],
"country": {

I did expect the cities array to be populated accordingly with all the cities available for the particular state.
Will appreciate if anyone can point out if the issue is with the schema/query or jpa mapping. As stated earlier the code is hosted on github @ https://github.com/samshers/graphQL-Starter

kaqqao
  • 12,984
  • 10
  • 64
  • 118
samshers
  • 1
  • 6
  • 37
  • 84
  • I see you're using an ancient version of graphql-java-tools and its [Spring Boot starter](https://github.com/graphql-java-kickstart/graphql-spring-boot). The naming of those artifacts is a total mess... but the new releases are under `com.graphql-java-kickstart` group id, so you should be using those instead. Do note that the Kickstarter project is independent from graphql-java (the core Java lib) team, and their own [Spring Boot starter](https://github.com/graphql-java/graphql-java-spring). Also, you tagged graphql-spqr but you're not using that at all. – kaqqao Sep 10 '19 at 14:40

1 Answers1

0

Late answer is better than no answer.

Lazy fetching issue

Your problem comes form your transaction management. This relationship

public class State {

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="state")
    List<City> cities;

is fetched lazily. A State's cities list is populated by JPA only when the list is accessed. If there is no transaction running when the list is accessed, then the list will stay empty.

The State data fetcher, stateRepository.findOne(stateName); finds the state object but does not populate its cities. Later, when the graphql-java framework tries to access the cities, there is no transaction running. Therefore the cities list stays empty.

How to solve

The easy and dirty way is to force EAGER fetching:

public class State {

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name="state")
    List<City> cities;

Other better solutions consist in telling graphql-java-tools to keep a transaction open until the response is sent back and are described in this question's accepted answer: LazyInitializationException with graphql-spring

AllirionX
  • 1,073
  • 6
  • 13