Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erratic class loading behavior in Spring Boot #177

Closed
kevinludwig opened this issue Sep 6, 2018 · 11 comments
Closed

Erratic class loading behavior in Spring Boot #177

kevinludwig opened this issue Sep 6, 2018 · 11 comments

Comments

@kevinludwig
Copy link

When using this JVM option, App Startup reports several warning messages of this type:

i.l.graphql.generator.OperationMapper    : Potential type name collision detected: 'ComponentBase' bound to multiple types: com.app.graphql.components.ComponentBase and com.app.graphql.components.ComponentBase. Assign unique names using the appropriate annotations or override the TypeInfoGenerator. For details and solutions see https://github.com/leangen/graphql-spqr/wiki/Errors#non-unique-type-name. If this warning is a false positive, please report it: https://github.com/leangen/graphql-spqr/issues.

Note that sometimes the two types listed are the same type, and other times they're the same type name but different packages. Actual queries post-startup fail (not all, but some), and not in ways that are easy to diagnose.

Not suggesting this is necessarily something you should fix but at the very least this should be front and center in the README as a limitation.

@kaqqao
Copy link
Member

kaqqao commented Sep 6, 2018

The same type name but different packages scenario is one of the main reasons that check is there :)

That's a legitimate name collision that you should take care of. If two types end up sharing a name (which is what is happening), it will have totally unpredictable behavior. I.e. failing in ways not easy to diagnose.

As for the class colliding with itself scenario, it's been reported once before but without any further info. Is the error message you show complete? I.e. is there no annotations mentioned in the log? Asking because the exact same class but with different annotations (e.g. annotations at the place of use) can easily end up mapped to different GraphQL types (think of Integer which gets mapped to Int and @GraphQLId Integer which gets mapped to String), so again the warning would be legit. If that's not the case, and it's really just the class itself, somehow colliding with itself, can you please try to provide an example? It would help a lot. I'll try the XX:+UseStringDeduplication arg in the mean time.

@kevinludwig
Copy link
Author

I dont believe the class used in the other package is exposed in graphql, is the thing. But ill double check that. Also all warnings disappear and the queries work perfectly without the jvm param, which is what makes it truely suspect to me.

@kevinludwig
Copy link
Author

With respect to same class, different annotations, are you referring to a case where I do something like this:

class SomeQuery {
    private MyImageType mainImage;
    private MyImageType fallbackImage;

    @GraphQLQuery(description="The main image")
    MyImageType main() {
         return mainImage;
    }

    @GraphQLQuery(description="Fallback image")
    MyImageType fallback() {
        return fallbackImage;
    }
}

I'm sure I have cases like that in my schema.

@kevinludwig
Copy link
Author

OK I have an update on this issue, firstly I was wrong! This does not have anything to do with -XX:+UseStringDeduplication. However, the runnable jar built by spring boot will, apparently randomly, sometimes start with these errors, and sometimes not. When I get these errors on startup, my queries are broken. When I do not get these errors on startup, everything works. I never get these errors when running under JUnit. I do use the spring test harness to start a full spring container in the tests and run queries via the public HTTP interface, so what my tests are doing is very similar to what the boot jar should be doing.

@kevinludwig
Copy link
Author

For reference the issue was a buggy version of classgraph (an internal dependency of graphql-spqr), by simply upgrading to latest version of that the issues went away.

@kaqqao kaqqao changed the title Errors when using JVM flag -XX:+UseStringDeduplication Erratic class loading behavior in Spring Boot Sep 8, 2018
@kaqqao
Copy link
Member

kaqqao commented Sep 8, 2018

Apart from updating ClassGraph, I also made sure to first try loading the concrete implementation classes using the same class loader that loaded the abstract super type. It delegate to ClassGraph only if this first attempt fails. It will also print a warning in this case. That should hopefully solve most if not all freak accidents like this one.

@kaqqao
Copy link
Member

kaqqao commented Sep 8, 2018

#179 also adds class loader info to the log when a name collision is detected. If another freak incident like this occurs, it should at least be easier to trace than this time.

@kicktipp
Copy link

I got these strange errors and I have no clue how to handle them:

i.l.graphql.generator.OperationMapper : Potential type name collision detected: 'String' bound to multiple types: java.lang.String (loaded by the bootstrap class loader) and @javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, payload=[], groups=[]), @javax.validation.constraints.Email(flags=[], regexp=.*, groups=[], message={javax.validation.constraints.Email.message}, payload=[]) java.lang.String (loaded by the bootstrap class loader). Assign unique names using the appropriate annotations or override the TypeInfoGenerator. For details and solutions see https://github.com/leangen/graphql-spqr/wiki/Errors#non-unique-type-name. If this warning is a false positive, please report it: https://github.com/leangen/graphql-spqr/issues.
The link is not helpful as the target #non-unique-type-name is not on this error page

@anita0711
Copy link

I got these strange errors and I have no clue how to handle them:

i.l.graphql.generator.OperationMapper : Potential type name collision detected: 'String' bound to multiple types: java.lang.String (loaded by the bootstrap class loader) and @javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, payload=[], groups=[]), @javax.validation.constraints.Email(flags=[], regexp=.*, groups=[], message={javax.validation.constraints.Email.message}, payload=[]) java.lang.String (loaded by the bootstrap class loader). Assign unique names using the appropriate annotations or override the TypeInfoGenerator. For details and solutions see https://github.com/leangen/graphql-spqr/wiki/Errors#non-unique-type-name. If this warning is a false positive, please report it: https://github.com/leangen/graphql-spqr/issues.
The link is not helpful as the target #non-unique-type-name is not on this error page

Hi, did you find any solution for this warning? I'm also getting the same thing. Any idea how to fix it?

@kaqqao
Copy link
Member

kaqqao commented Jun 7, 2020

@kicktipp @anita0711 These are false warnings, safe to ignore. Will be fixed in the next release.

@anita0711
Copy link

anita0711 commented Jun 7, 2020

@kicktipp @anita0711 These are false warnings, safe to ignore. Will be fixed in the next release.

@kaqqao Thank you for your quick revert.

I'm getting __typename for my query where I expect field names of a model. Could this issue be due to the above warning?

I have below 2 models as below:

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
public class CoResponse {

  @JsonProperty("tempId")
  private String tempId;

  @JsonProperty("cId")
  private String cEid;

  @JsonProperty("cType")
  private CoType type;

  @JsonProperty("status")
  private String statusCode;

  private String statusMessage;

  @JsonProperty("result")
  private CoResult resultMetadata;
}

and

@Getter
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonDeserialize()
@JsonSerialize()
@Accessors(fluent = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CoResult {
	
	@GraphQLQuery(name = "resourceId")
	@JsonProperty()
	private String resourceId;

	@GraphQLQuery(name = "resourceUrn")
	@JsonProperty()
	private String resourceUrn;

	@GraphQLQuery(name = "resourceIds")
	@JsonProperty()
	private String[] resourceIds;

	@GraphQLQuery(name = "resourceUrns")
	@JsonProperty()
	private String[] resourceUrns;

	@GraphQLQuery(name = "createdDate")
	@JsonProperty()
	private Instant createdDate;

	@GraphQLQuery(name = "revisionId")
	@JsonProperty()
	private String revisionId;

	@GraphQLQuery(name = "errorData")
	@JsonProperty("error")
	private ErrorData errorData;

	/**
	 * Convert to json string.
	 */
	public String toJson() {
		return JsonUtil.objectAsJsonString(this);
	}

	/**
	 * Convert from json string.
	 */
	public static CoResult fromJson(String json) {
		return JsonUtil.parseJsonAsObject(json, CoResult.class);
	}

}

When I try to fetch the fields of CoResponse along resultMetadata field, instead of getting the field names(resourceId, resourceUrn, revisionId, etc.), I could see '__typename' something as follows:

query{
  getCommandById(cId:"dfh79384hjdfhj"){
    body{
      resultMetadata{
        __typename        # expecting the sub-fields of resultMetadata here (resourceUrn, resources, etc.)
      }
    }
  }
}

I'm using graphql-spqr-spring-boot-starter library. Could you please suggest why am I not able to fetch the fields of resultMetadata? Any kind of help will be much appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants