JSON
入力 Pojo インスタンスを取得する必要があり、Jackson 2
ライブラリを使用しており、以下のreadValue
メソッドは typeReferencing を使用して逆シリアル化できます。
POJO_ClassName p = mapper.readValue(new TypeReference< POJO_ClassName >() {});
しかし、問題は、POJO
実行時に動的に作成およびロードされるため、上記のステートメントの完全修飾クラス (POJO_ClassName) 名がないため、どうすればインスタンス/オブジェクトにアクセスできるかということですJSON
。POJO
注:jsonSchema2pojo
ライブラリを使用POJO
して、実行時にクラスを生成します。
ここにコードスニペットがあります。実行時に生成するPOJO
ために使用しJSON
、試しています
String classPath="com.EnrichmentService.Thread72";
String classLocation = System.getProperty("user.dir")
+ "/src/main/java"; JCodeModel codeModel = new JCodeModel();
final RuleFactory ruleFactory = new RuleFactory(config,
new Jackson2Annotator(config), new SchemaStore());
final SchemaMapper mapperSchema = new SchemaMapper(ruleFactory,
new SchemaGenerator());
mapperSchema.generate(codeModel, "EsRootDoc",classPath, json);
codeModel.build(new File(classLocation)); // generates pojo classes
// Till above jsonSchema2Pojo pojo generation all Good !!
// EsRootDoc instance is needed for further drools drl validations.
com.EnrichmentService.Thread72.EsRootDoc p = mapper.readValue(new TypeReference<com.EnrichmentService.Thread72.EsRootDoc>() {});
// see alternative way as well in my 24Aug17 edit at the end of this question
しかし、com.EnrichmentService.Thread72.EsRootDoc
まだ生成されていないため、コンパイラはクラスが見つかりませんでした。
主なポイント:
1) 実行時に同じ Pojo クラスが繰り返し生成されますが、JSON 入力が毎回変化するため、プロパティが異なります。
2) Object pojo =mapper.readValue(json,Class.forName("com.EnrichmentService.Thread72.EsRootDoc")); も試しました class.forName は既存のクラスを置き換えません!
編集 24 Aug17 - これが私のカスタムクラスローダーです:
注: インデクサーは、実行時に動的な EsRootDoc/POJO クラスをロードするクラスです。
static class TestClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals("com.EnrichmentService.Thread72.EsRootDoc")) {
try {
InputStream is = Indexer.class.getClassLoader().getResourceAsStream("com/EnrichmentService/Thread72/EsRootDoc.class");
byte[] buf = new byte[is.available()];
int len = is.read(buf);
Class<?> c=defineClass(name, buf, 0, len);
resolveClass(c);
return c;
} catch (IOException e) {
throw new ClassNotFoundException("", e);
}
}
return getParent().loadClass(name);
}
}
別の方法として、上記の TestClassLoader カスタム クラス ローダーを使用してみましたが、次のようになります。
Class cls = new TestClassLoader().loadClass("com.EnrichmentService.Thread72.EsRootDoc");
Object obj = cls.newInstance();
cls.getMethod("getCrawlerSource").invoke(obj);
p=mapper.readValue(json, cls); // but here i am getting the same deserialization exception as earlier.
古い回答を参照 @ How to replace classes in a running application in java ?
Edit2: 24Aug17 例外が直面している stackTrace はこちら: https://pastebin.com/ckCu2uWx