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

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

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

Related

Unable to use #spring annotations when class object is new

Actually i am having a spring main class as follows.
ClassLoader loader = null;
try {
loader = URLClassLoader.newInstance(new URL[]{new
File(plugins + "/" + pluginName + "/" + pluginName +
".jar").toURI().toURL()}, getClass().getClassLoader());
} catch (MalformedURLException e) {
e.printStackTrace();
}
Class<?> clazz = null;
try {
clazz = Class.forName("com.sample.Specific", true, loader);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method method = null;
try {
method = clazz.getMethod("run",new Class[]{});
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
method.invoke(clazz.newinstance,new Object[]{});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Specific Class is follow :
package com.sample
#Service
public class Specific {
#Autowired
private FD fd;
public void run(){
fd.init();
}
}
#Autowired FD comes to be null. Can anyone give me some solution as i also know new operator will not work for #autowired. As i am loading class with new instance then only it becomes null. Can anyone guide me in this thing
Spring has its own way to provide you new objects. As long as you're consistent using #Autowired and #Component/#Service/#Repository/#Controller there should be no problem
And since all "business" object instantiation is handled by Spring you should never use new. If you have no other way of getting an instance (something I realy doubt about it) you can use ApplicationContext.getBean() but as I said, in most cases this is not required (and this is also a bad practice)
If you need several instances of a class instead of injecting them (by using #Autowired) you can inject a Provider<T>
UPDATE
Since the class is known at runtime you need to inject an ApplicationContext and use it to get the bean:
public class TheClassWhereYouAreCreatingTheObject {
#Autowired
private ApplicationContext context; // You definitely need this
public void theMethodWhereYouAreCreatingTheObject() {
Class<?> clazz = ... // getting the object class
Object instance = context.getBean(clazz); // getting and instance trough Spring
// If you know that kind of object you will get cast it at call its methods
((Specific) instance).run();
// If you know anything about the class you will have to use reflection
Method method = clazz.getMethod("run", new Class[]{});
method.invoke(instance, new Object[]{});
}
}
Add Specific Service bean inside your main class. As long as the service is inside one your component scan packages then you shall be fine. Do not use new operator.
#Autowired
private Specific specific;
If you want to take advantage of autowiring then I think we have to think from spring terms.
you can use Beanutils to create a new instance and play with reflections supporting spring features.
Please go through below methods:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/BeanUtils.html

Liferay transactional method

I want to call method filterFindByG_U from DLFileEntryUtil. The problem is, that the method in which I call filterFindBy must be transactional. But I dont know how to do this. I tried to write an annotation #Transactional before the method declaration but this didn't help. Can someone please give me some idea how to do this in Liferay 6.2? The method that should be transactional is:
public List<DLFileEntry> filterEntriesPermissions(User user) {
List<DLFileEntry> filtered = new ArrayList<DLFileEntry>();
try {
filtered = DLFileEntryUtil.filterFindByG_U(user.getGroupId(), user.getUserId());
} catch (SystemException | PortalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return filtered;
}
I will be thankful for some help and explanation.
Try this method:
DLFileEntryLocalServiceUtil.getGroupFileEntries(user.getGroupId(), user.getUserId(), QueryUtil.ALL_POS, QueryUtil.ALL_POS);

Cannot get JAXBContext?

In my java project i have a jar that i generated with some classes. I am able to instantiate the instance of the class that is in my jar:
Alert a = new Alert();
But wen i try to do this:
JAXBContext context = JAXBContext.newInstance(Alert.class);
I get run time exception like this:
java.lang.InternalError:
Error occured while invoking reflection on target classes. Make sure all referenced classes are on classpath: interface javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter
Exception: null
Any idea what could be the issue?
Thank you
This happened to me as I had defined XmlAdapter implementations that were in a different JAR and not on the classpath. When trying to create the JAXBContext, it needs these adapters used by the JAXB type. Now that I figured this out, the message makes more sense, but is still very cryptic. XmlJavaTypeAdapter is the annotation interface and the code fails to call the value() method of the annotation as it returns Class<? extends XmlAdapter>, a class type which is not defined on the classpath.
If you look at the code that throws the exception, this is impossible:
public Class More ...getClassValue(Annotation a, String name) {
try {
return (Class)a.annotationType().getMethod(name).invoke(a);
} catch (IllegalAccessException e) {
// impossible
throw new IllegalAccessError(e.getMessage());
} catch (InvocationTargetException e) {
// impossible
throw new InternalError(e.getMessage());
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
Would be nice if the cause of the exception was not lost.

Why is there no InputManager.getInstance() for me? And injectInputEvent()?

I'm trying to develop a service that injects touch events to the system while the service interacts with some hardware/remote server. I've googled and everyone suggests using the InputManager class, referencing Monkey as an example project to follow.
However, there is no getInstance() method for me in InputManager! All I have access to is exactly what the documentation shows. No getInstance() method, and most importantly, no injectInputEvent() method.
My build target SDK is Android 4.1.2, and my AndroidManifest.xml file specifies a target SDK version of 16 (I've tried changing the min target to 16 too, which didn't help (plus I'd like to keep it at 8 if possible)).
How on earth can I use InputManager like Monkey does? Where are the methods Monkey is using, and why can't I use them?
You cannot inject input events to one application from other application. Also you cannot inject events to your own application from within application. https://groups.google.com/forum/?fromgroups=#!topic/android-developers/N5R9rMJjgzk%5B1-25%5D
If you want to automate, you can use monkeyrunner scripts to do the same.
Class cl = InputManager.class;
try {
Method method = cl.getMethod("getInstance");
Object result = method.invoke(cl);
InputManager im = (InputManager) result;
method = cl.getMethod("injectInputEvent", InputEvent.class, int.class);
method.invoke(im, event, 2);
}
catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Maybe this is a bit late but could be helpful for future reference.
Method 1: Using an instrumentation object
Instrumentation instrumentation = new Instrumentation();
instrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
instrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
Method 2: Using internal APIs with reflection
This method uses reflection to access internal APIs.
private void injectInputEvent(KeyEvent event) {
try {
getInjectInputEvent().invoke(getInputManager(), event, 2);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
private static Method getInjectInputEvent() throws NoSuchMethodException {
Class<InputManager> cl = InputManager.class;
Method method = cl.getDeclaredMethod("injectInputEvent", InputEvent.class, int.class);
method.setAccessible(true);
return method;
}
private static InputManager getInputManager() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<InputManager> cl = InputManager.class;
Method method = cl.getDeclaredMethod("getInstance");
method.setAccessible(true);
return (InputManager) method.invoke(cl);
}
injectInputEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
injectInputEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
Please note that method 1 is a clean solution based on public API and internally it uses the same calls from method 2.
Also note that neither of this two methods can be invoked from the MainThread.

How do I get a methods parameters as IJavaElements in Eclispe jdt 3.6?

For compatibility reasons, I have to adapt my Eclipse Plugin from JDT 3.7 to 3.6. Unfortunately, the old version doesn't seem to have the handy .getParameters() method yet.
I need to display an ElementTreeSelectionDialog to the user, allowing him to browse through methods of a class and select a parameter of a method. For this, I have written a ITreeContentProvider with this straightforward getChildren - method:
public Object[] getChildren(Object paramObject) {
if(paramObject instanceof ICompilationUnit){
ICompilationUnit icu = (ICompilationUnit) paramObject;
try {
return icu.getAllTypes()[0].getMethods();
} catch (JavaModelException e) {
e.printStackTrace();
}
}
if(paramObject instanceof IType){
IType type = (IType) paramObject;
try {
return type.getMethods();
} catch (JavaModelException e) {
e.printStackTrace();
}
}
if(paramObject instanceof IMethod){
IMethod method = (IMethod) paramObject;
try {
return method.getParameters();
} catch (JavaModelException e) {
e.printStackTrace();
}
}
return null;
}
I'd like to stick to the interfaces to be able to use the JavaUILabelProvider, which displays everything with proper icons, Signatures etc.
So the tricky part is to either create valid LocalVariable objects from the parameters or some other valid IJavaElement implementation, which would be displayed properly by JavaUILabelProvider.
I have tried creating an array of LocalVariable[], but this doesn't really work out, since I can't find any way to get the necessary position markers and Annotation objects for the elements...

Categories

Resources