Jackson deserialisation/TypeReference for dynamically loaded pojo class

Viewed 5993

I have a requirement to get JSON input Pojo instance and I am using Jackson 2 library and below readValue method could deserialise using typeReferencing :

POJO_ClassName p = mapper.readValue(new TypeReference< POJO_ClassName >() {});

But the problem is that as POJO is created and loaded at runtime dynamically, how do I get JSON to POJO instance/object as I do not have fully qualified class (POJO_ClassName) name for above statement?

Note: I use jsonSchema2pojo library to generate POJO classes at runtime.

Here is code snippet, I am using to generate POJO for JSON at runtime and trying

  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

But as com.EnrichmentService.Thread72.EsRootDoc has yet not been generated compiler would error to class not Found.

Main Points:

1) Same Pojo classes generated at run time iteratively but with different properties as JSON input changes each time.

2) Even tried Object pojo =mapper.readValue(json,Class.forName("com.EnrichmentService.Thread72.EsRootDoc")); as class.forName does not replace an existing class!

Edit 24 Aug17 - Here is my custom class loader :

Note: Indexer is class which load dynamic EsRootDoc/POJO class at run time.

 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);
            }
        }

I have tried using above TestClassLoader custom class loader as an alternative way is like this :

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.

Referred an old answer@ How to replace classes in a running application in java ?

Edit2: 24Aug17 Exception being faced stackTrace is here: https://pastebin.com/ckCu2uWx

3 Answers
Related