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
Related
I have a general layout with some custom nodes, each with its own Controller. As I want to inject the same object into every of these Controllers, in order to share data between them, I create a custom ControllerFactory.
To set the ControllerFactory for the root node, I have the following working code in the start method of the Main (extends Application) class:
FXMLLoader loader = new FXMLLoader(getClass().getResource("layout.fxml"));
Main self = this;
loader.setControllerFactory((Class<?> param) -> {
return self.instantiateController(param);
});
The instantiateController method in turn just creates a new of the passed class for the moment, and logs what kind of Class was instantiated:
public Object instantiateController(Class<?> c) {
Object o = null;
try {
o = c.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
System.out.println(o.getClass() + " instantiated");
return o;
}
This way, I can observed which Controllers were instantiated. It is always just the Controller of the root element, never of one of the custom nodes. Even though they get instatiated and are displayed as wanted, they never get factored by my factory. This way, I can not inject the object I want. How can I make the factory to be applied on all nested Controllers?
I'd like to instantiate an object with it's constructor outside a method. Example:
public class Toplevel {
Configuration config = new Configuration("testconfig.properties");
public void method1() {
config.getValue();
...etc
}
}
If I do this right now...I get this error..
Default constructor cannot handle exception type IOException thrown by implicit super constructor. Must define an explicit constructor
I'd like to do something like this so I could call config anywhere in my class, right now I keep having to instantiate the Configuration objects...there's gotta be a way to do this...any help would be much appreciated, thanks in advance.
EDIT:
Configuration class:
public class Configuration {
private String mainSchemaFile;
public Configuration() {
}
public Configuration( String configPath ) throws IOException {
Properties prop = new Properties();
prop.load( new FileInputStream( configPath ));
this.mainSchemaFile= prop.getProperty("MAINSCHEMA_FILE");
}
Your Configuration constructor is declared to throw an IOException. Any code that instantiates a Configuration using this constructor must catch it. If you use a variable initializer, then you can't catch it, because you can't supply a catch block; there is no block you can put here, only an expression. There is no method to declare a throws clause on either.
Your alternatives:
Instantiate the Configuration in a Toplevel constructor. You can catch the exception in the constructor body, or you can declare that constructor that it throws the exception.
public class Toplevel {
Configuration config;
public Toplevel() {
try {
config = new Configuration("testconfig.properties");
} catch (IOException e) { // handle here }
}
// ...
Instantiate the Configuration in an instance initializer in the TopLevel class, where you can catch the exception and handle it.
public class Toplevel {
Configuration config;
{
try {
config = new Configuration("testconfig.properties");
} catch (IOException e) { // handle here }
}
// ...
Catch and handle the exception in the Configuration constructor, so calling code doesn't have to catch the exception. This isn't preferred, because you may have an invalid Configuration object instantiated. Calling code would still need to determine if it's valid.
public class Configuration {
// Your instance variables
private boolean isValid;
public Configuration( String configPath ) {
try {
// Your code that might throw an IOE
isValid = true;
} catch (IOException e) {
isValid = false;
}
}
When you create a new Toplevel object then you have not declared a specific constructor for it and the attribute of Toplevel is instantiated as your code describes it with Configuration config = new Configuration("testconfig.properties");
So you do not handle the IoException of the Configuration constructor!
A better way would be to declare a specific constructor of Toplevel like this:
public Toplevel(){
try{
this.config = new Configuration("testconfig.properties");
} catch (IOException e) {
// handle Exception
}
}
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);
In CDI 1.2 there is a way to check if a class instance is proxified? I need this because I need to get the name of original class, not the proxy name.
#Inject Bean bean;
public void sysout() {
// will print something like com.Bean$$Weld9239823
System.out.println(bean.getClass());
// I don't know how to check if the bean instance if a proxy or real class instance
}
Using Weld classes I can do this job:
public void sysout() {
// will print true because this is a proxy
System.out.println(ProxyObject.class.isAssignableFrom(bean));
// will print com.Bean
System.out.println(((TargetInstanceProxy) bean).getTargetInstance());
}
In CDI 1.1 there is no method to do this. I search inside CDI 1.2 docs if a method was added about this, but I don't found anything.
So... I miss something and CDI 1.2 there is a method to get original class name and instance? Or if not, there is a plain to add this feature in near feature?
For Weld on WildFly do this:
public boolean isProxy(Object obj) {
try{
return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
} catch (Exception e) {
log.error("Unable to check if object is proxy", e);
}
return false;
}
To retrive actual object instead of proxy (I need to serialize it) I do this:
public Object getObject(Object obj) {
Field f = null;
boolean isAccessible = false;
try {
for(Field fi : Class.forName(handler).getDeclaredFields()) {
if(fi.getName().equals(field)) {
f = fi;
isAccessible = f.isAccessible();
f.setAccessible(true);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
if(f == null) {
throw new RuntimeException(new NoSuchFieldException(String.format(
"The required field '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
field, method)));
} else {
try{
obj = f.get(getHandler(obj));
for(Method m : Class.forName(instance).getMethods()) {
if(m.getName().equals(value)) {
return m.invoke(obj);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
f.setAccessible(isAccessible);
}
throw new NoSuchMethodError(String.format(
"The required method '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
value, instance));
}
}
Be aware, that it is the darkest magic as possible, have very poor performance and can break at any WildFly update, if they change classes, methods for fields in it.
This is a terrible hack, but for Weld (and possibly other implementations) you can check if the class name contains "Proxy": possibleProxy.getClass().getSimpleName().contains("Proxy"). I use it only for logging purposes to get a cleaned up version of the wrapped class name:
/**
* Get the actual simple name of the objects class that might be wrapped by
* a proxy. A "simple" class name is not fully qualified (no package name).
*
* #param possibleProxy an object that might be a proxy to the actual
* object.
* #return the simple name of the actual object's class
*/
public static String getActualSimpleClassName(final Object possibleProxy) {
final String outerClassName = possibleProxy.getClass().getSimpleName();
final String innerClassName;
if (outerClassName.contains("Proxy")) {
innerClassName = outerClassName.substring(0, outerClassName.indexOf('$'));
} else {
innerClassName = outerClassName;
}
return innerClassName;
}
you can make a method inside your proxied cdi bean like
public String getClassName() {
return this.getClass().getName();
}
this is not the best solution, but a simple pragmatic way to get the class name through the proxy... the downside of this is that the method must be on every implementation...
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.