How to load manual objects created via reflection into spring context - java

There are two application. Main Application and Utility Application where utility Application is packaged as jar in Main application. Both are spring boot application.
In utility application I create an object of a class A which is present in Main Application using reflection API.
Class A has one Autowired instance variable defined in it. Issue is when Utility Application tried to run some method one the same class A object, then that autowired variable results in null.
I guess, since I am creating the object manually that is why it is not managed by Spring.
Now my question is how can provide this object to spring context so that any Autowiring happening inside the class A actually gets autowired.
Below is the code samples
under Main Application
package m.main.application.A;
class A implements Action{ //Action interface coming from utility application
#Autowired
private Calculator calculator
#override
public void execute(){
calculator.add(5+2); //Here calculator is null. Autowire is not working
}
}
Utility Application packaged as Jar in Main Application
Class Util{
public createObjectAndRun(){
Class<?> class = Class.forName("com.main.application.A");
Action newObject= (Action) class.getConstructor().newInstance();
//executing execute
newObjects.execute(); //This fails as calculator is not autowired
}
}
I want to know if there is a way we can make calculator gets autowired properly.

Your class A is not annotated with any spring stereotype (#Service, #Component, etc), so it's not a spring managed bean. So one way you could achieve this would be making it a spring bean (using a stereotype) and get it through ApplicationContext's method getBean on your Util class.

Related

How to call Spring Framework repositories methods

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring

I need multiple instances of a Controller in a Spring/JavaFX app

I am trying to integrate JavaFX with Spring for the autowiring capabilities of Spring.
However I need to have multiple instance of myController class which I have yet been able to configure.
Using fxmlLoader.setControllerFactory(springContext::getBean);, everytime I load the fxml file, I get the same instance of the myController class.
Without that line, I get different instances but the autowired myService inside myController is null.
What can I do to get this to work?
Thanks
Configure the controller to have prototype scope (the service can still have the default singleton scope, so each instance of the controller has a reference to the same instance of the service).

Why Dependency Injenct only works in Resource class in jersey

I am trying to use test database for my application. I am using MyBatis.
I have 2 environments configured in MyBatis configuration file. I have set property like so in my ResourceConfig subclass.
property("Env","development");
I am able to get this value i,e development in my Resource like fallows
#Context Application app;// this is instance variable
System.out.println(app.getProperties().get("Env"));// this statement in resource method
I have 3 layers Controller(i,e Resource class), Action Layer and DAO and DMO mapper layer.
But the above 2 statements which are working in resource class is not working in DAO class. I am getting a NullPointerException at System.out.println Line
Now I have to get the environment in Resource and pass it to further layers. Is there a better way to do this.
All I want is to choose test database for testing and development database for development
Most likely because you are just trying to instantiate the DAO youself
#Path("boogers")
class Resource {
Dao dao = new Dao()
}
That's not going to work. The Dao needs to go through Jersey's injection system. The resource works because it goes through the injection system. If you want to do the same for your Dao, then you need to inject it and let it go through the DI system. That way the system will inject it with required dependencies before injecting it into the resource
#Path("boogers")
class Resource {
#Inject
Dao dao;
}
Here, you don't instantiate it, You let the DI system create it and inject it. To make it work, you need to make the Dao injectable.
class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindAsContract(Dao.class);
}
});
}
}
Here you're binding the Dao class to the injection system, so that whenever it sees #Inject Dao, it will be able to grab/create it and inject it.

Is Spring bean just a shared object

I am trying to understand purpose of Spring-created beans. Are they just global shared object (such that they are declared like
#Component
public class MySpringBean{},
and later this object is used anywhere like inside some class
public class MyClass {
#Autowired
MySpringBean mySpringBean;
}
)?
Can their internal creation/implementation assumed like this? -
public class MyApp {
MySpringBean mySpringBean;
}
and used in MyClass like -
public class MyClass {
MySpringBean mySpringBean = MyApp.mySpringBean;
}
Its the object valid for only that class hierarchy. In your case Spring just create an object for mySpringBean and will keep it available for MyClass. Internally its more like
MySpringBean mySpringBean = new MySpringBean()
But actually
all Spring beans are managed - they "live" inside a container, called "application context".
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
so in your case both mySpringBean and an instance of MyClass will be in application context.
Based on your question, I believe you should know about how beans are managed by Spring (or how Spring manages the life cycle of beans from initialization to destroy). But also note that you don't have to go into too much of details (wells, it's a framework that's is providing you). Yes, it's definitely true to init involves using new operator. These objects live inside the Container and Spring wires them whenever it's called for. Since beans are managed by Spring, you can implement callback methods too.

Spring : Create beans at runtime

I am working on a module which needs spring beans to be created at runtime. My driver app is a spring boot app, it needs to create a bean (which is outside the component scan packages of the app) and invoke a method in that bean. Fully qualified class name and method name will be runtime parameters. Below is an example:
Bean to be created:
#Component
#ComponentScan(basePackages = {"com.test"})
public class TestClass {
#Autowired
private AnotherTestClass anotherTest;
public void test(){
System.out.println("In test");
anotherTest.test();
}
}
Here is the driver class code (which obviously doesn't work):
public void test(){
try{
Class testClass = Class.forName("com.test.TestClass");
Object newInstance = testClass.newInstance();
applicationContext.getAutowireCapableBeanFactory().autowireBean(newInstance);
Method testMetod = testClass.getMethod("test");
testMetod.invoke(newInstance, null);
}catch(Exception e){
e.printStackTrace();
}
}
Here, applicationContext is autowired.
As it is instantiating the class via reflection, the object won't have autowired dependency set. What I want to achieve is, to scan all the packages (as mentioned in the component scan annotation), create the beans and set the dependencies. i.e. I want to do exactly the same as what spring does when application starts, but at runtime.
Also, I want it to be completely generic as the beans will mostly be residing in external jars and fully qualified class path and method name will be passed at runtime (like a pluggable architecture).
Any ideas how to achieve this?

Categories

Resources