I got a strange case. In the given database, I got a record that has a VARCHAR
field, so in my entity model I added this field, plus getters and setters. Now is the
I think a better solution is to change your architecture, but If you are forced to it try the following :) This code you can find here
public class DynamicProxy {
public interface CalculateScore {
double calculate(double score);
}
private static class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
private static class JavaClassObject extends SimpleJavaFileObject {
protected final ByteArrayOutputStream bos = new ByteArrayOutputStream();
public JavaClassObject(String name, Kind kind) {
super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
}
public byte[] getBytes() {
return bos.toByteArray();
}
@Override
public OutputStream openOutputStream() throws IOException {
return bos;
}
}
private static class ClassFileManager extends ForwardingJavaFileManager {
private JavaClassObject classObject;
private final String className;
public ClassFileManager(StandardJavaFileManager standardManager, String className) {
super(standardManager);
this.className = className;
}
@Override
public ClassLoader getClassLoader(Location location) {
return new SecureClassLoader(DynamicProxy.class.getClassLoader()) {
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
if (name.contains(className)) {
byte[] b = classObject.getBytes();
return super.defineClass(name, classObject.getBytes(), 0, b.length);
}
return super.findClass(name);
}
};
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, javax.tools.JavaFileObject.Kind kind, FileObject sibling) throws IOException {
classObject = new JavaClassObject(className, kind);
return classObject;
}
}
private static class MyInvocationHandler implements InvocationHandler {
private final String className;
private final String classBody;
public MyInvocationHandler(String implClassName, String classBody) {
this.className = implClassName;
this.classBody = classBody;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class> clazz = compileClass(className, classBody);
return method.invoke(clazz.newInstance(), args);
}
}
private static Class> compileClass(String className, String classBody) throws Throwable {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnostics = new DiagnosticCollector();
JavaFileObject file = new JavaSourceFromString(className, classBody);
Iterable extends JavaFileObject> compilationUnits = Arrays.asList(file);
JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null), className);
CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
boolean success = task.call();
for (Diagnostic extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.println(diagnostic.getCode());
System.out.println(diagnostic.getKind());
System.out.println(diagnostic.getPosition());
System.out.println(diagnostic.getStartPosition());
System.out.println(diagnostic.getEndPosition());
System.out.println(diagnostic.getSource());
System.out.println(diagnostic.getMessage(null));
}
if (success) {
return fileManager.getClassLoader(null).loadClass(className);
}
return null;
}
@SuppressWarnings("unchecked")
public static T newProxyInstance(Class clazz, String className, String classBody) {
ClassLoader parentLoader = DynamicProxy.class.getClassLoader();
return (T) Proxy.newProxyInstance(parentLoader, new Class[] { clazz }, new MyInvocationHandler(className, classBody));
}
public static CalculateScore create(String body) {
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class CalculateScoreImpl implements pl.softech.stackoverflow.javac.DynamicProxy.CalculateScore {");
out.println(" public double calculate(double score) {");
out.println(body);
out.println(" }");
out.println("}");
out.close();
return newProxyInstance(CalculateScore.class, "CalculateScoreImpl", writer.toString());
}
public static void main(String[] args) {
CalculateScore calculator = create("if (score <= 0.7) {return 0;} else if (score <=0.8) {return 1;} else if (score <=0.9) {return 2;} else {return 3; }");
System.out.println(calculator.calculate(0.3));
}
}