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