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

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

Related

How to create a non reusable bean on springboot

By default, on springboot, when we declare a method with #Bean, the object instance will be shared across all objects that request for #Autowired that class...
What if I want spring to deliver different instances for each autowire class that request that object?
I mean instead of share one single instance of a bean have multiple "disposable" beans for each requisition of that object?
Why I want that?
the reason is quite simple, RestTemplateBuilder is a common bean used in most spring application, by its nature this builder is STATEFUL which means that any changes made to one class to its structure will cause side effects to all other objects that use it.
If you want to have a different instance for each class you inject you should use the scope annotation as follow:
#Bean
#Scope("prototype")
public Person personPrototype() {
return new Person();
}
you can also use the constant as follow:
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

How to load manual objects created via reflection into spring context

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.

How spring controller class object instantiated?

I have a question that, i have a spring-mvc based project which is accessible by multiple user. My question is that when more than one user access that application then for each user there is separate controller class object or all user access the same controller class object.
There will be multiple controller instances for different requests.
Please read:
http://docs.spring.io/spring-framework/docs/2.5.x/reference/mvc.html
Related answer:
How does Spring MVC handle multiple users
If the controller is a bean (which is the usual case) then the default is one bean per Spring container context.
If you set the controller/bean to scope=prototype then you would get a new instance from the factory each time.

Howto get #Service instance in Spring programatically

I need to implement javax.faces.convert.Converter to convert String-to-Object and Object-to-String.
To do so, I have defined specific services (#Service), but I do not know how to get an instance.
I have tried to use #Autowired and #Component to get instance, but Spring is ignoring.
Is it possible to get #Service instance from FacesContext?
It's impossible. Spring annotations are useless if it didn't configure to use them in your applications.
First You should get the application context like this
ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
Then use this context to get instance of the component.
YourService custB = (YourService )ctx.getBean("yourService");

How do you use spring's injection for unit testing a controller?

I want to test my spring mvc controller.
The controller has a service:
#Autowired
UserService userService
And my user service depends on (autowired) my UserDao and some other services like mongoDb etc.
Now I want the business logic to be tested in my UserService, but ofcourse I want to mock the responses from my UserDao and Mongodb etc.
How do I setup my unit test correctly?
Can I re-use the spring container's xml file that has all my beans etc. or do I create a new one? (I'm assuming I have to get the spring container involved here)
Looking for some guidance on this, any tutorials would be greatly appreciated.
Update
What I find strange is that for my spring controller (that doesn't implement from Controller) I was able to access my private varialbe to manually set my service, i.e:
#Controller
public class UserController {
#Autowired
UserService userService;
}
And in my unit test I could do:
UserController controller = new UserController();
controller.userService = ....
But for my UserService, which has UserDao autowired, I can't access the userDao property:
UserService userService = new UserServiceImpl();
userService.userDao = .... // not available
It makes sense since it is private, but how is it working for my controller?
Spring framework has very interesting features for testing. You can take a look at Spring reference guide. It can provide DI even in your JUnit test class.
#RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "/applicationContext.xml" and "/applicationContext-test.xml"
// in the root of the classpath
#ContextConfiguration(locations={"/applicationContext.xml", "/applicationContext-test.xml"})
public class MyTest {
// class body...
}
Briefly, you can use your own applicationContext.xml or even define a new one just for testing. I personally use a different one since I define another dataSource dedicated for testing purposes.
What I find strange is that for my spring controller (that doesn't implement from Controller) I was able to access my private varialbe to manually set my service, i.e:
This is easy: the varible in not private.
It has the default visibility ("package private"). This mean you can access them from all classes of the same package.
So if you have a common structure, then the controller and the controller test case are in the same package. Therefore you can modify the ("package private") controller fields. But the controller test case and the service are not in the same packaged, so you can not access the ("package private") service fields.
Can I re-use the spring container's xml file that has all my beans
etc. or do I create a new one? (I'm assuming I have to get the spring
container involved here)
I would advice against creating new xml file. You would end up duplicating lot of stuff and its going to be hard to maintain. There would be proliferation of config files. You put the config required for tests in a different xml and that should not even be deployed to your production box. So far as using the config for your beans, you can employ the mechanism as suggested by #Trein.
For testing spring contrller in general, you may also find this SO Thread useful.
Hope that helps.

Categories

Resources