How should each class in an application retrieve the Spring application context? - java

How should each class in an application retrieve the Spring application context? Or, stated another way, how many times should an application invoke new ClassPathXmlApplicationContext("applicationContext.xml")?

Usually a class does not need the application context, but it needs some of the objects Spring injects. And this is configured in that applicationContext.
As such an application typically calls new ClassPathXmlApplicationContext("applicationContext.xml") only once.

With dependency injection, you shouldn't have to, in general. But if your class really needs to be aware of the application context, implement the ApplicationContextAware interface. Spring will automatically call the setApplicationContext method defined in that interface to provide your class with the application context.
Note that if you're trying to gain access to filesystem resources, you should use ResourceLoaderAware. If you want access to the message source, then don't implement an interface; instead, inject a reference to the MessageSource bean.

I think you should take the advice from the answer to your other question here. Implementing ApplicationContextAware or ServletContextAware (if you are in a servlet container) is the best way to get the context.
Look up how spring handles Dependency Injection or Inversion of Control.

Once.
Actually you should let Spring do the heavy lifting and build/configure the classes rather than the other way around.
The whole idea is that all classes can be built without having to call the outside world for dependencies, which are 'magically' provided by the Spring framework.
This approach was invented to get away from the ServiceLocator pattern to which you are alluding, i.e. get a reference to an object to get the dependencies you need, ala JNDI.

Related

Do action before spring context created

How can I execute the action, before Spring context created? I found only one solution that more or less can satisfy me, it is listening ApplicationStartingEvent but I don't know how correctly do it because Spring doesn't see listener bean because context not created yet. So maybe someone knows ways how to catch ApplicationStartingEvent or maybe another better solution to do it.
Interface ApplicationContextInitializer could suffice for your requirement.
Read ApplicationContextInitializer documentation
Implementing ApplicationContextInitializer allows you to do additional tasks/initializations before persistent bean definition is loaded (i.e. your application-context.xml). One such use is, when you want to select profiles before you will load definitions.

How to handle Spring beans required by library?

I am refactoring an application using Spring by moving some shared components (a webservice client) into a library. The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
I have created a #Configuration class so the application only needs to #Import it to use the library, but the application also needs to supply a Jackson ObjectMapper and a Settings object containing how to contact the webservice. I autowire the ObjectMapper and Settings beans into various beans used in the library. The application uses the library by injecting the Client into its code and calling it.
This works, but I'm not sure it's the right style. In IntelliJ IDEA as I develop the library, it complains that the beans the library injects don't exist with a red underline, which is true, they don't exist. But normally when I see red all over files that cannot be resolved, that tells me maybe I'm not doing it the right way.
The library needs to be used with applications using Spring 3 and 5. What is the proper way for a library to ask for things like ObjectMapper when it's not appropriate to define its own (because the app will already have Jackson), and "proprietary" beans like the Settings object?
Your question is a bit broad but hopefully I can give you a hint to the right direction.
The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
First: This components should use an interface instead of some concrete beans.
Second: If you have a reusable library then this typical needs some configuration, that can not been part of the library itself because it depends on application that use that library
Third: because of second (and first): your library should not been based on any form of auto wiring, instead your library should been based on explicit (or default) configuration.
And this solve the problem. Use interfaces and an explicit configuration of your library in your application. As well as add an good documentation of the needed configuration to your lib.
Using inspiration from #Kayaman and #Ralph, I decided it's not appropriate to expose Spring as a part of a library to be used directly from the application's context. I realize now it's also not appropriate because the library could define duplicate "private" beans it did not want to expose. I was overthinking it. If I wanted to use Spring, I found out I could do this:
public class Factory {
public static Client createClient(ObjectMapper mapper, Settings settings) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("mapper", mapper);
beanFactory.registerSingleton("settings", settings);
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(beanFactory);
ctx.registerBean(ClientConfiguration.class);
ctx.refresh();
return ctx.getBean(Client.class);
}
}
Essentially, it's OK to use Spring as an implementation detail. Since the configuration I made exposed only one bean, it makes sense as a factory method. In the application I would create a method like this:
#Bean public Client makeClient(ObjectMapper mapper, Settings settings) {
return Factory.createClient(mapper, settings);
}
Of course the Bean method would have ObjectMapper and Settings injected in from the application's context, or could be inline constructors for ObjectMapper/Settings.
Instead, what I decided was since the client had few enough beans and none were lazy, I just removed Spring annotations entirely and just built the object graph by hand in almost as much code as the spring context took. Now the library has the benefit of not requiring Spring at all at runtime, in a supposed non-Spring application.

Is it possible to access the Spring Application Context without implementing ApplicationContextAware?

I am debugging a Java application which uses the Spring IoC Container. I have a breakpoint set in one of the methods of a class annotated as a #Component. I would like to get my hands on the Spring Application Context which manages this bean (to access some different bean, which hasn't been injected into this class).
Since I don't want to modify the code, implementing ApplicationContextAware is out of question.
How could I do this? Is this even possible?
You can do it, no need to implement ApplicationContextAware.
You can #Autowire the application context
private #Autowired ApplicationContext appContext;
EDIT
without any code modification, what you need is a good profiling tool. MaybeJProfiler can do the trick, or some free alternative.

instantiate model object in jsp web project

Im writing an web application using the MVC design pattern.. the application should connect to a RMI server providing the business part (Model)
my problem is, I dont know where i should instantiate the model class and connect to the RMI, providing access to all servlets.. i added a ServletContextListener and shared the reference on the servlet context, but i dont think that is the right way to do it
thanks in advance
You can instantiate your Model/Business classes from your Controller. Better still make a single instance (Just Create One) of each in the start of the application. You can also go lazy-loading about it.
Instantiating Model/Business classes from your JSPs means, instantiating them from View. That, of course, violates the MVC pattern.
Either you can make your Model/Business classes as Singleton, or keep the reference in Servlet Context. Both are fine and the latter is more test friendly. The former can be made test friendly too, if you don't specify the constructor as private but just have a common understanding that it's not there for instantiating it everywhere.

Spring framework best practices: deploying a non-bean compliant component

I want to build an MVC app using Spring (first timer here).
As such I want to embed Jetty as the servlet engine. Jetty however doesn't stricly follow the java beans pattern, so I can't launch some classes from Spring (they use overloaded setters or non setter init methods like addXYZ).
What is the accepted/recommended practice for structuring this project? Obviously all my code fits nicely in the MVC model, but for Jetty:
Do I encapsulate all of Jetty (or any
other non-bean friendly component) in
my own Spring-friendly bean?
Do I try to instantiate as much of it as
possible in spring and just extend
classes that aren't bean con-formant
to make them act like proper beans?
Is there
another option?
Generally speaking, I'm for the 2nd point - i.e. try to use spring utilities like factory-method, init-method, <constructor-arg> and things like that to overcome the fact that something is not entirely spring-friendly. It is rarely the case that it's impossible to configure beans with spring. And for the cases when it is impossible, create wrappers
You can also instantiate the 3rd party beans programatically:
via a FactoryBean
via JavaConfig

Categories

Resources