Build and test the Morphia project using Maven. Use when compiling, running tests, or building artifacts.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a test fails and you need to diagnose the root cause. Run the test, read errors, trace through generated and source code, fix, and verify.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
Systematic diagnosis of test failures in the Morphia project. Run the test, read the full error, trace the root cause through source and generated code, fix minimally, and verify.
Run the failing test
./mvnw test -pl :module-name -Dtest="ClassName#methodName" -Ddeploy.skip=true
-Ddeploy.skip=true to skip dokka-am with -Dtest= (applies test filter to all modules)./mvnw install -pl :dep1,:dep2 -DskipTests -Ddeploy.skip=true -Dinvoker.skip=true
Read the full error - stack trace, error message, line numbers. Don't skip anything.
Find relevant code - Read both source AND generated code:
src/main/, src/test/target/test-classes/ - use javap -c -p ClassName to decompiletarget/generated-sources/~/.m2/repository/ source jars with unzip -pTrace the root cause - Follow the error backward:
core/src/main/java/dev/morphia/critter/parser/generator/ (see "Critter Code Generation" below).__read*/__write* methods) or the runtime path (hidden nestmate accessors)?PropertyAccessorGenerator boxes primitives)Fix minimally - One change at a time. Rebuild affected modules:
./mvnw install -pl :morphia-core,:critter-maven -DskipTests -Ddeploy.skip=true -Dinvoker.skip=true
Verify - Re-run the failing test AND related tests in the same class.
Critter generates bytecode with the Class-File API (java.lang.classfile), using the
jdk-classfile-backport library (package io.smallrye.classfile) so it runs on Java 17.
There is no Gizmo or ASM in the generators. Everything is in
core/src/main/java/dev/morphia/critter/parser/generator/, and CritterGenerator is the entry point.
| Generator | Produces |
|---|---|
AddFieldAccessorMethods / AddMethodAccessorMethods | AOT only: rewrites the entity class to add synthetic __readXxx/__writeXxx methods |
PropertyAccessorGenerator | AOT only: a PropertyAccessor that calls the woven __read*/__write* methods |
NestmateAccessorGenerator | Runtime only: a PropertyAccessor using direct getfield/putfield/invokevirtual, defined as a hidden nestmate (Lookup.defineHiddenClass(..., NESTMATE)) and registered in NestmateAccessorRegistry |
PropertyModelGenerator | A CritterPropertyModel per property |
EntityModelGenerator | The CritterEntityModel for the entity |
VarHandleAccessorGenerator | A VarHandle/MethodHandle-based accessor; not used by the main pipeline right now (only TestVarHandleAccessor) |
The two paths:
critter-maven (generate-models / generate-test-models) calls CritterGenerator.generate(type, loader, false).
It writes the generated models and the woven entity classes to disk under __morphia/<entity>/.CritterMapper calls generate(type, loader, true).
That defines classes in a CritterClassLoader plus hidden nestmates. If it fails, it logs once and falls back to a reflective EntityModel.
Hidden nestmates need full privilege access, so an entity outside Morphia's module (on the classpath: loaded by a different
class loader) fails with a NestmateAccessException; CritterMapper logs a specific "can't access ... isn't in Morphia's
module" warning for it. That's expected for those layouts, and the fix is critter-maven AOT models, not a generator change.PropertyFinder rejects some entities for AOT with UnsupportedOperationException("AOT skip: ..."):
inherited fields the entity can't reach and whose declaring class can't be rewritten (e.g. a private field in a library
superclass), fields shadowing a superclass field, array-typed fields, and entities whose @Id is on a getter.
Entities with no @Id at all (e.g., embedded types) are generated normally. A final field's __writeXxx sets it through
a cached java.lang.reflect.Field, since putfield may only write a final field from a constructor. An inherited field from a superclass in the
same output directory or jar gets its __readXxx/__writeXxx methods woven into that superclass, which the entity
inherits. The rejected entities use runtime generation instead, so an "AOT skip" warning in the critter-maven output is
expected for them and is not an error.
| Error | Likely Cause |
|---|---|
AbstractMethodError | A generated class is missing an interface method. Generators emit methods with explicit erased descriptors (e.g. get(Ljava/lang/Object;)Ljava/lang/Object;), and nothing adds bridge methods for you |
VerifyError / Bad type on operand stack | Usually a primitive/reference mismatch: a primitive was used where an Object was expected, or the reverse, without boxing or unboxing |
ClassCastException in a generated accessor | checkcast to the wrong owner (for an inherited field, the declaring class vs the entity class) or to the wrong wrapper type |
IllegalAccessError from a nestmate accessor | The hidden class was defined against the wrong lookup class. It must be privateLookupIn the field's declaring class |
NoSuchMethodError __read*/__write* | The AOT accessor ran against an unwoven entity class, e.g. the woven class from generated-classes/critter is not ahead of the original on the classpath |
ClassNotFoundException __morphia.* | Critter code generation didn't run or class not registered |
invokestatic Wrapper.valueOf(prim)Wrapper. Unboxing: checkcast Wrapper, then invokevirtual Wrapper.xxxValue().
Helpers live in GenerationUtils (PRIMITIVE_TO_WRAPPER, primitiveUnboxMethod, primitiveClassDesc).checkcast only accepts reference types. To get a primitive from an Object, cast to the wrapper and then unbox.Object in __read*/__write* signatures for reference types,
and the cast happens inside the entity.javap -c -p. AOT output is under target/generated-classes/critter (main) or
target/test-classes/**/__morphia/ (tests). Runtime-generated classes are in memory only.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Build and test the Morphia project using Maven. Use when compiling, running tests, or building artifacts.
日本語の概要は準備中です。原文の説明を表示しています。