ebean-orm / ebean

Ebean ORM
https://ebean.io
Apache License 2.0
1.46k stars 260 forks source link

Assoc QueryBeans are broken after upgrading to 15.6.0 #3484

Closed tobias- closed 5 minutes ago

tobias- commented 6 days ago

TL;DR NoSuchMethodError when using basic functionality of QueryBeans.

Skipping a lot of needed boiler plate to focus on the problem.

@Entity
public class Foo {
    public Bar bar;
}

@Entity
public class Bar {
    public String id;
}

new QFoo(database)
  .bar.id.eq("foo")

The beans will not get the necessary constructors added when building this with :

Decompiled version of the generated+transformed Foo._bar() method:

  public query.assoc.QAssocBar<query.QFoo> _bar();
    Code:
       0: aload_0
       1: getfield      #114                // Field query/assoc/QAssocBar;
       4: ifnonnull     22
       7: aload_0
       8: new           #111                // class query/assoc/QAssocBar
      11: dup
      12: ldc           #105                // String email
      14: aload_0
      15: iconst_1
      16: invokespecial #211                // Method query/assoc/QAssocBar."<init>":(Ljava/lang/String;Ljava/lang/Object;I)V
      19: putfield      #114                // Field email:Lquery/assoc/QAssocBar;
      22: aload_0
      23: getfield      #114                // Field email:Lquery/assoc/QAssocBar;
      26: areturn

The only constructors in the class Bar after transformation are:

  public query.assoc.QAssocBar(java.lang.String, R, java.lang.String);
  public query.assoc.QAssocBar(java.lang.String, R);

After investigation, it seems the (partial) is the improvedQueryBeans concept used in TypeQueryClassAdapter that was added in September. If the ebean-version is >= 145 (which it is in ebean-api), query beans are defined as "improved". This means that the beans are not transformed to get the extra constructors.

In FieldInfo.writeMethod there is no concept of improved, thus the constructor called is QAssocBar(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;I)V

Expected behavior

Being able to use query bean associated beans.

Actual behavior

java.lang.NoSuchMethodError: 'void query.assoc.QAssocBar.<init>(java.lang.String, java.lang.Object, int)'

--edit I forgot to add that the query beans I generate are in Kotlin, but the code seems to take the same paths, only the generation of the QueryBeans are different.

rbygrave commented 21 hours ago

What is the querybean-generator version? Or are you using the kotlin-querybean-generator?

I can kind of tell that this is using older generated query beans because the QAssocBar would not be generated with the new generator. That is, the "improved" query beans now generate a QBar.AssocOne and QBar.AssocMany with one for ToOne relationships and the other for ToMany relationships. This is so that filterMany() etc ONLY are available on ToMany paths.

My suspicion is that you are using the kotlin-querybean-generator? ... as that hasn't been updated yet.

Now, that all said, the "improved" query beans change actually had 2 changes and the second change was that [in theory] there were 2 additional constructors generated for "Assoc Beans" and that these constructors were no longer needed or necessary and so we could toggle off the generation of those constructors. HOWEVER ...

However in ebean-agent we still see a case which uses that constructor with the third parameter I type. So I note that we have that bug there in ebean-agent 15.6.0 regardless of the generator.

I can't reproduce this issue though with 15.6.0 of querybean-generator as that will always bypass that problematic code in ebean-agent. Hmmm.

rbygrave commented 21 hours ago

Are yes, looks like kapt("io.ebean:kotlin-querybean-generator") ... so that will generate the older query bean code. I should be able to reproduce.

rbygrave commented 31 minutes ago

Fix in ebean-agent 14.6.1 & 15.6.1 via https://github.com/ebean-orm/ebean-agent/pull/215

rbygrave commented 5 minutes ago

This has been fixed in 14.6.1 (and 15.6.1) of the ebean-agent and that has been deployed.

Upgrade to the ebean gradle plugin version 14.6.1.

This issue was reproduced and fix confirmed in the gradle Kotlin example app, see: https://github.com/ebean-orm/examples/blob/master/basic-gradle-kotlin/build.gradle#L3