0

この質問は、私の以前の質問に関連しています: How to create a default constructor with Byte Buddy

メソッド呼び出しをいくつかのインスタンスに委譲する前に、最初にいくつかのコンテキストを設定するサブクラスを作成しています。これはすでに非常にうまく機能しており、1 つの問題が残っています。

動的に作成されたサブクラスをロードすると、次のエラーが発生します。

    java.lang.VerifyError: Bad access to protected data in invokevirtual
Exception Details:
  Location:
    com/frequentis/ps/service/test/saga/ProxyTestSaga$ByteBuddy$Rm8DV3Lj.setTimeoutManager(Lcom/codebullets/sagalib/timeout/TimeoutManager;)V @3: invokevirtual
  Reason:
    Type 'com/frequentis/ps/service/test/saga/ProxyTestSaga' (current frame, stack[0]) is not assignable to 'com/frequentis/ps/service/test/saga/ProxyTestSaga$ByteBuddy$Rm8DV3Lj'
  Current Frame:
    bci: @3
    flags: { }
    locals: { 'com/frequentis/ps/service/test/saga/ProxyTestSaga$ByteBuddy$Rm8DV3Lj', 'com/codebullets/sagalib/timeout/TimeoutManager' }
    stack: { 'com/frequentis/ps/service/test/saga/ProxyTestSaga' }
  Bytecode:
    0x0000000: b200 0cb6 0010 57b1                    

    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredField(Class.java:2068)
    at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:124)
    at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:200)
    at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:200)
    at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.initialize(DynamicType.java:3497)
    at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:3485)
    at com.frequentis.ps.service.test.saga.DynamicSagaTypeBuilder.buildAndLoad(DynamicSagaTypeBuilder.java:65)
    at com.frequentis.ps.service.test.saga.MoreAbstractSpaceSagaUnitTest.generateProxyClassForSagaUnderTest(MoreAbstractSpaceSagaUnitTest.java:274)
    at com.frequentis.ps.service.test.saga.AbstractSpaceSagaUnitTest.enhance(AbstractSpaceSagaUnitTest.java:105)
    at com.frequentis.ps.service.test.saga.ProxyTestSagaTest.before(ProxyTestSagaTest.java:27)

setTimeoutManagerこれは現在私のバイト バディ セットアップです。表示されたエラーが発生する " " および " setState" メソッドを 除いて、ほぼすべてのケースで機能します。

// called within the unit test base class (as shown in the call stack above)
builder = new ByteBuddy()
    .subclass(sagaUnderTestClass, ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC);
    // define default ctor if necessary that passes "null" values to the super ctor
    builder.method(isAnnotatedWith(StartsSaga.class).or(isAnnotatedWith(EventHandler.class)))
           .intercept(MethodDelegation.to(new ForwardingContextSetupInterceptor<(sagaUnderTest, contextSetter))
                                      .appendParameterBinder(Pipe.Binder.install(Forwarder.class)))
           .method(isPublic()
                           .and(isDeclaredBy(sagaUnderTest.getClass()).or(isDeclaredBy(AbstractSaga.class)
                           .and(not(isAnnotatedWith(StartsSaga.class))).and(not(isAnnotatedWith(EventHandler.class))))
           .intercept(MethodDelegation.to(sagaUnderTest))))

セッターには別のセットアップが必要ですか?
それとも抽象クラスが原因ですか?
保護されたデータへのアクセスが悪いと言っている理由がよくわかりません。プライベートフィールドを意味しますか?

私の型階層はこんな感じです。セッターを宣言する最上位の基本クラス:

public abstract class AbstractSaga<SAGA_STATE extends SagaState> implements Saga<SAGA_STATE>, NeedTimeouts, NeedContext {
    private SAGA_STATE state;
    private boolean completed;
    private TimeoutManager timeoutManager;
    private ExecutionContext context;

    protected AbstractSaga() {
        completed = false;
    }

    // i have omitted some method for clarity

    protected ExecutionContext context() {
        return context;
    }

    @Override
    public SAGA_STATE state() {
        return state;
    }

    @Override
    public void setState(final SAGA_STATE state) {
        this.state = state;
    }

    @Override
    public boolean isFinished() {
        return completed;
    }

    protected void setFinished() {
        completed = true;
    }

    @Override
    public void setTimeoutManager(final TimeoutManager timeoutManager) {
        this.timeoutManager = timeoutManager;
    }
}

拡張:

public abstract class AbstractSpaceSaga<SAGA_STATE extends SpaceSagaState, MESSAGE extends Message> 
    extends AbstractSaga<SAGA_STATE> {
}

最後に、次のように拡張します。

public class ProxyTestSaga 
    extends AbstractSpaceSaga<SpaceSagaState, TestRequest> {

    @StartsSaga
    public void handle(final TestRequest request) {
    }

    @EventHandler
    public void handle(final TestEvent event) {
    }
}

コードが何とか理解できることを願っています。必要に応じていつでも情報を追加できます。

4

2 に答える 2