• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Instantiating a generic class at runtime with a type of class that is created at runtime

 
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi everyone

I am looking for a way to instantiate a generic class at runtime with a class which is also created at runtime.

Here is my code overview

I have a config.json file which helps me to build classes with attributes, getters and setters (POJO if this is the correct name to give).

e.g.







When I try to instantiate the MyUtility class with the Class.forName("MyPojo.class") it doesn't like it.
Is there any way to instantiate the MyUtility class at runtime with the MyPojo.class which I also create at runtime?

Thanks
 
Ranch Hand
Posts: 121
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Nick.

There is no class MyUtility<Something> at runtime. All "generic" instances uses MyUtility.class as an implementation. This class is called type erasure (official term, you can find it in a java language specification). So, following code yield true:


There are some differences in field/method signatures which uses this class, but not in an actual Class object used. So you should creates an instance of "erased (without type arguments)" class and pass it arguments. Casting of values received from MyUtility<T>.utilityMethod() will be automatically performed in the code which actually uses that concrete instances of the generic type.
 
nick tomer
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the info Maxim. I did some reading on what you said and I understood what you mean and why my class architecture does not work currently.

Do you have any suggestions on how I could achieve this level of flexibility that I am looking for in runtime? Is Class<?> more close to what I am looking for?

Thanks
 
Maxim Karvonen
Ranch Hand
Posts: 121
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You may use Class<?> as an argument. You even may use a Class<T> in some cases. For example you may have following method:



In this method you must put instances of class T into a resulting list. If all added elements are compatible to a type T then all will work fine. But you can't check that object is an instance of T if T is generic type. For example, compiler won't help you to ensure safety in a following code (you will be able to add String to a list, for example):


I don't see how much genericity you need in your example. If you always use only concrete types with "plain" object fields (i.e. fields have no generic type) you original approach may be fine. But I suggest something like


Inside a method you may use type parameter <T>. Just remember, that if T is generic, it can't be checked using reflection and type mismatch will result in classCastExceptions in other places, not an acutal reflection code. So, following code should be fine (not tried to compile):



It is a good approach to try to do thing as safe as possible. But you will need a "class" object and it will still have some limitations. And if you have no class instance you may try to use an unchecked conversion. Or it may be better to return Class<?>/Object instance and let a user to cast it to a proper instance (but due to an erased types he won't be able to check if List is a List<Integer> or a List<String>).

I don't yet understand what exactly you are trying to do. But I hope this examples will guide you insights to your problem.
 
nick tomer
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks again. I am trying to follow your answer but I need to read some stuff before I get a clear view of your answer.

Let me explain to you what I am really trying to do.

I am working on creating a Rest web service using Apache CXF. The web service does the simple thing of fetching data from a database and presenting them in xml.

In my database I have one table called "servers"

table:servers:
col:vendor
col:ram
col:name

and one table called "locations"

table:locations
col:longitude
col:latitude


So, I have created a POJO for each of these tables as below





So the WS for the servers connects to my DB and fetches a ResultSet of servers. Then I have a class called ResultSetToObjectList<Server> where I pass the ResultSet and it returns me a List<Server> list with all the data of the ResultSet.

Then I just return a Response.status(Status.OK).entity(new GenericEntity<List<Server>>({}).build(); and I get XML back.

Here is how my WS looks like




The problem with my current implementation is that each time that I want to get data from another table of my database then I have to create a new POJO for the new table and create a new WS resource class to deal with my new resource type (e.g. employees).

What I am trying to do is to drive a new WS resource creation with only a configuration file. Lets say that I was to be able to get data from a new table called employees. If the table have two columns only "name" and "surname" then I want to give add the json code below to a config.json file that I have and the Web Service to be able to create automatically the Employee POJO at runtime and according to the request URL to return appropriate data back. For example the localhost:8080/rest/servers/get will return servers' data back and the localhost:8080/rest/employees/get will return employees' data back. But I will not have to write not even one line of code for that. The Web Service will pick up automatically all the required info from the config.json file in order to decide what data to return. And all these has to happen at run time. This is why I wanted to have generics that will be resolved at runtime (something that i was totally wrong :P). Do you have now a more clear view on what I am trying to do?



 
Maxim Karvonen
Ranch Hand
Posts: 121
12
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now I understand your problem better.

Probably Responce.entity does not use any information about generic types. It use actual values to create an output. I think it makes no difference to write a List<Object> or a List<Server> if they contains same values. You may safely create a list of Objects and pass it to a writer.

Or, as I said, you may create a some kind of a "type-safe" handler passing a bean class to a handler constructor. Thus a handler will be parametrized with a bean class and some metadata (such as a table name, etc...). It may even resolve bean fields at an instantiation time to reduce reflection overhead. And in a bean configuration you just use a Class<?>.

Something like


But you may be unlucky. While I wrote an example I found an anonymous inner class (child of GenericEntity). It is a bad sign. It may mean that Response actually uses generic type info. And it is a common trick to create an anonymous class to catch actual generic arguments type.

Let's clarify a difference. When you have an instance of GenericEntity<T> (but not of a child class) then you can not exctract any concrete value of type T. This kind of types is erased at runtime. But then you can create a non-generic child class. This is a brand new class (and also a new type). In this class you may extract information about "generic" parent type. Yes, this class inherits its implementation from it parent (and actually an "erased" class is it's parent). But this new class have information about how it's generic types relates with a parent generic types. For example, using Class.getGenericSuperclass you may know, which arguments was passed to a parent class. If child is a generic class itself this information may contain references to this child type arguments. But since child is a concrete (although anonymous) class, it has no type arguments and genericSuperclass will have all fields as "concrete values".

Just repeat following thought in other words. There is no difference between different instantiations of a same type. They are all same ".class" at a run-time. And because there is no difference, you cannot create a new "instance" of a generic type at a runtime. But you can extract information parent's type arguments form a child type. And, of course, different children (anonymous inner classes still are childern) are different classes (each children have it's own class file). So, creating child classes may be a solution.

Wrapping things up. You cannot create an instance of a "generic" type. But even you are unlucky, you still may handle a situation! Now you know, that some information is saved in child classes. So you need to generate two classes. One class for a bean. And other for a child class which can store generic information. Try to find a class named like ServersResource$GenericEntity$1.class or ServersResource$1.class in your compiled output (sorry, I forgot a proper naming scheme for an anonymous inner classes. But they are clearly distinguishable by suffixed like $<number>). You second generated class should be similar to that anonymous child (of course, using a properly constructed general type argument).

And you handler will be like this:

All required information can be extracted now from new wrapper class (which is a child to a GenericEntity). Yes, you now need to create two class files (one for bean and one for wrapper). And generation of proper wrapper is not easy (generic type info is ignored at a runtime in most JVM parts and generic signatures are not easy by itself). But if you have no other choices, this is doable. And you may generate a non-anonymous (named) descendant from a GenericEntitiy if it is simplier, JVM does not distinguish anonymous and named classes (all classes have it's name in JVM).

P.S. Among other choices there is a possibility to not to use a CXF and create own writer. In this case you map store table data as a list of simple hashmaps and serialize it using via a custom writer. But it may be not possible. And some libraries provides a way to construct "generic type" representation itself in some form (so you pass a "type" object and a value object).
P.P.S. Primary tool for analyzing existing bytecode files (including anonymous classes) is javap, which is included in JDK. You may use it to look up signatures in that anonymous inner classes and use it as a guide in a generating you new wrapper types.
 
nick tomer
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Maxim

I just got back from my holidays. I ll have a good look at your answer because some concepts are new to me so I will let you know when I got something.

Thanks
 
reply
    Bookmark Topic Watch Topic
  • New Topic