dimanche 15 janvier 2023

Cannot inject already loaded type

I want to add some variables to the Author class, using the bytebuddy library. The problem that is displayed to me after the second call to the apply method is

Exception in thread "main" java.lang.IllegalStateException: Cannot inject already loaded type: class pl.edu.testowy.entity.Author

I have no idea how to fix this, I know it's probably about classLoader

package pl.edu.wat.testowy.reflection;

package pl.edu.wat.testowy.reflection;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.pool.TypePool;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static net.bytebuddy.matcher.ElementMatchers.named;

public class Reflection {
    private TypeDescription entityDefinition;
    private TypeDescription requestDefinition;
    private TypeDescription responseDefinition;

    private TypeDescription mapperDefinition;
    private TypePool typePool;
    private ByteBuddy byteBuddy;

    public Reflection() {
        this.typePool = TypePool.Default.ofSystemLoader();
        this.byteBuddy = new ByteBuddy();
        this.entityDefinition = typePool.describe("pl.edu.wat.testowy.entity.Author").resolve();
        this.requestDefinition = typePool.describe("pl.edu.wat.testowy.dto.AuthorRequest").resolve();
        this.responseDefinition = typePool.describe("pl.edu.wat.testowy.dto.AuthorResponse").resolve();
        this.mapperDefinition = typePool.describe("pl.edu.wat.testowy.mapper.AuthorMapper").resolve();

    }


    FieldInformation fieldInformation = new FieldInformation();
    FieldInformation2 fieldInformation2 = new FieldInformation2();


    //nie beda to pola final bo one beda sie zmienialy
    public static void apply(String test){

        var ref = new Reflection();
        ref.applyEntity(test);
        ref.applyRequest(test);
        ref.applyResponse(test);
        ref.applyAuthorMapper(test);

    }

    public List<String> getFieldNames() {
        FieldInformation2.readJson("fields2.json");
        List<FieldInformation2> fields = FieldInformation2.getFields();
        List<String> fieldNames = new ArrayList<>();
        fields.forEach(f -> fieldNames.add(f.getFieldName()));
        return fieldNames;
    }

    private void applyAuthorMapper(String test) {//musimy wyciagnac mappera

        DynamicType.Builder <Object> builder = byteBuddy
                .redefine(mapperDefinition,
                        ClassFileLocator.ForClassLoader.ofSystemLoader())
                .method(named("fillAuthorRequest"))
                .intercept(MethodCall.invoke(setterAuthorEntity(test))
                        .onArgument(0)
                        .withMethodCall(MethodCall
                                .invoke(getterRequest(test))
                                .onArgument(1)))
                .method(named("fillAuthor"))
                .intercept(MethodCall.invoke(setterAuthorResponse(test))
                        .onArgument(0)
                        .withMethodCall(MethodCall
                                .invoke(getterEntity(test))
                                .onArgument(1)));

        try(var unloadedAuthor = builder.make()){
            mapperDefinition = unloadedAuthor.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                    .getTypeDescription();

        } catch(IOException e){
            throw new RuntimeException();
        }

    }

    private MethodDescription getterEntity(String test){
        return  entityDefinition
                .getDeclaredMethods()
                .filter(ElementMatchers.isGetter(test))
                .stream()
                .findFirst()
                .orElseThrow();
    }
    private MethodDescription setterAuthorResponse(String test) {
        return  responseDefinition
                .getDeclaredMethods()
                .filter(ElementMatchers.isSetter(test))
                .stream()
                .findFirst()
                .orElseThrow();
    }

    private MethodDescription getterRequest(String test) {
        return  requestDefinition
                .getDeclaredMethods()
                .filter(ElementMatchers.isGetter(test))
                .stream()
                .findFirst()
                .orElseThrow();
    }

    private MethodDescription setterAuthorEntity(String test) {
        return  entityDefinition
                .getDeclaredMethods()
                .filter(ElementMatchers.isSetter(test))
                .stream()
                .findFirst()
                .orElseThrow();
    }

    private void applyResponse(String test) {

        DynamicType.Builder <Object> builder = byteBuddy
                .redefine(responseDefinition,
                        ClassFileLocator.ForClassLoader.ofSystemLoader())
                .defineProperty(test,typePool.describe("java.lang.String").resolve());

        try(var unloadedAuthor = builder.make()){
            responseDefinition = unloadedAuthor.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                    .getTypeDescription();


        } catch(IOException e){
            throw new RuntimeException();
        }

    }

    private void applyRequest(String test) {
        DynamicType.Builder <Object> builder = byteBuddy
                .redefine(requestDefinition,
                        ClassFileLocator.ForClassLoader.ofSystemLoader())
                .defineProperty(test,typePool.describe("java.lang.String").resolve());

        try(var unloadedAuthor = builder.make()){
            requestDefinition = unloadedAuthor.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                    .getTypeDescription();


        } catch(IOException e){
            throw new RuntimeException();
        }

    }

    public void applyEntity(String test) {
        DynamicType.Builder <Object> builder = byteBuddy
                .redefine(entityDefinition,
                        ClassFileLocator.ForClassLoader.ofSystemLoader())
                .defineProperty(test,typePool.describe("java.lang.String").resolve());

        try(var unloadedAuthor = builder.make()){
            entityDefinition = unloadedAuthor.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                    .getTypeDescription();

        } catch(IOException e){
            throw new RuntimeException();
        }

    }



}


package pl.edu.wat.testowy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import pl.edu.wat.testowy.reflection.Reflection;


@SpringBootApplication
public class TestowyApplication {

    public static void main(String[] args) {
        //tak jak tu korzystam z mechanizmu refleksji tak wystarczy utworzyc zalozmy 10 obiektow, gdzie podajemy nazwe i typ zmiennej
        Reflection.apply("test");
        Reflection.apply("test2");
        SpringApplication.run(TestowyApplication.class, args);
    }

}

I have tried modifying the classLoader but to no avail, not too sure how.





Aucun commentaire:

Enregistrer un commentaire