Search code examples
javagenericsreflectiongetconstructor

Create instance of Generic class at runtime with getConstructor(): NoSuchMethodException()


am using generics and need to create an instance of a generic class at runtime, so I am trying to use getConstructor(). Unfortunately, I receive a NoSuchMethodException despite having the correct signature, so I am at a loss as to what is wrong. I will appreciate your suggestions so I can get beyond this issue. :) I've provided the constructors for CustomerAssembler. I need to create an instance of this class, dynamically, due to generics being used. I've included the snippet of code that I am using. In it, I called getConstructors() to see whether the constructors exist and their signatures. Both constructors exist and I have used the proper signature, so I don't know why I keep getting this exception. Arggg... Hopefully, you will see what I am doing wrong. :)

Thank you for your time and help, Mike

 // Here are the constructors for CustomerAssembler.

    public CustomerAssembler()
    {
        super();
    }   

    public CustomerAssembler(
            Class<Customer> entityClass, 
            Class<CustomerPreviewDTO> entityPreviewDTOClass, 
            Class<CustomerDetailDTO> entityDetailDTOClass,
            Class<CustomerUpdateDTO> entityUpdateDTOClass,
            EntityManager entityManager)
    {
        super(entityClass, entityPreviewDTOClass, entityDetailDTOClass, entityUpdateDTOClass, entityManager);
    }

Here is the exception: NoSuchMethodException:

java.lang.NoSuchMethodException: assemblers.CustomerAssembler.<init>(entities.Customer, dtos.CustomerPreviewDTO, dtos.CustomerDetailDTO, dtos.CustomerUpdateDTO, javax.persistence.EntityManager)

Here is the code...

    try
    {
        Class<CustomerAssembler> customerAssemblerClass = CustomerAssembler.class;

        Constructor<CustomerAssembler>[] lst = (Constructor<CustomerAssembler>[]) this.customerAssemblerClass.getConstructors();

/* See what the signature is for the non-default constructor, so I can make sure that
           getConstructor() is configured properly.  Here is what was reported in the debugger:

           [0] = {java.lang.reflect.Constructor@10796}"public assemblers.CustomerAssembler()"

           [1] = {java.lang.reflect.Constructor@10797}"public assemblers.CustomerAssembler(java.lang.Class,java.lang.Class,java.lang.Class,java.lang.Class,javax.persistence.EntityManager)"
     signature = {java.lang.String@10802}"(Ljava/lang/Class<Lentities/Customer;>
                                                   Ljava/lang/Class<dtos/CustomerPreviewDTO;>
                                                   Ljava/lang/Class<dtos/CustomerDetailDTO;>
                                                   Ljava/lang/Class<dtos/CustomerUpdateDTO;>
                                                   Ljavax/persistence/EntityManager;)V"
        */

        // Configure our constructor call...  this.contactAssemblerClass
        Constructor<CustomerAssembler> ca =
                customerAssemblerClass.getConstructor(
                        Customer.class,
                        CustomerPreviewDTO.class,
                        CustomerDetailDTO.class,
                        CustomerUpdateDTO.class,
                        EntityManager.class);

    // Create an instance here...

    }
    catch (NoSuchMethodException e)
    {
        e.printStackTrace();
    }
    catch (InstantiationException e)
    {
        e.printStackTrace();
    }
    catch (IllegalAccessException e)
    {
        e.printStackTrace();
    }
    catch (InvocationTargetException e)
    {
        e.printStackTrace();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

Solution

  • customerAssemblerClass.getConstructor(
                        Customer.class,
                        CustomerPreviewDTO.class,
                        CustomerDetailDTO.class,
                        CustomerUpdateDTO.class,
                        EntityManager.class);
    

    This looks for a constructor that has the following signature:

    CustomerAssemble(Customer c,
                     CustomerPreviewDTO cpDTO, 
                     CustomerDetailDTO cdDTO, 
                     CustomerUpdateDTO cuDTO, 
                     EntityManager em)
    

    Your constructor doesn't take that as argument. It takes 4 instances of Class, and an instance of EntityManager.

    So the code should be

    customerAssemblerClass.getConstructor(
                        Class.class,
                        Class.class,
                        Class.class,
                        Class.class,
                        EntityManager.class);