ApplicationContext.xml bean execution - How? - java

I've applicationContext.xml which contains below line:
<bean id="myclass" class="com.abc.myclassinfo" >
</bean>
And, myclassinfo.java has below code:
public class myclassinfo {
public myclassinfo() {
// Here I'm initializing Jersey client
}
}
Now, what happens when spring loads the applicationContext.xml? Does it invoke this constructor?
Also, if I want to insitialize the Jersey client some other way without applicationContext.xml, how do I do that?
Thanks!

First, it calls the constructor (the no-arg one by default, or another one if annotated)
Then it calls a #PostConstruct / init-method
Then it calls postprocessors that can manipulate the object further
IF you want to use the class outside spring, you just instantiate it (using the constructor), and manually invoke the init method (if such exists). Note that you lose the automatic proxies that spring creates around your objects for transactions, scheduling, caching, etc.

Try to use init-method or #Postconstruct annotation for init some logic.

Seems like a log statement would have cleared up the first question pretty quickly.
Your second question isn't totally clear to me. You can use annotations, and skip at least most XML. I'm not aware that the Jersey client stuff has a hard dependency on Spring, however.
If you want to use Spring without a config file and without annotations, you can build a context programmatically, although I'm not sure why you'd want to do this, except possible for testing. Even then, it's easier to just extend an existing context, IMO.

Related

Why is Spring's ApplicationContext.getBean with Interface considered bad? [duplicate]

I asked a general Spring question: Auto-cast Spring Beans and had multiple people respond that calling Spring's ApplicationContext.getBean() should be avoided as much as possible. Why is that?
How else should I gain access to the beans I configured Spring to create?
I'm using Spring in a non-web application and had planned on accessing a shared ApplicationContext object as described by LiorH.
Amendment
I accept the answer below, but here's an alternate take by Martin Fowler who discusses the merits of Dependency Injection vs. using a Service Locator (which is essentially the same as calling a wrapped ApplicationContext.getBean()).
In part, Fowler states, "With service locator the application class asks for it [the service] explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.
Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it [Inversion of Control] unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative."
I mentioned this in a comment on the other question, but the whole idea of Inversion of Control is to have none of your classes know or care how they get the objects they depend on. This makes it easy to change what type of implementation of a given dependency you use at any time. It also makes the classes easy to test, as you can provide mock implementations of dependencies. Finally, it makes the classes simpler and more focused on their core responsibility.
Calling ApplicationContext.getBean() is not Inversion of Control! While it's still easy to change what implemenation is configured for the given bean name, the class now relies directly on Spring to provide that dependency and can't get it any other way. You can't just make your own mock implementation in a test class and pass that to it yourself. This basically defeats Spring's purpose as a dependency injection container.
Everywhere you want to say:
MyClass myClass = applicationContext.getBean("myClass");
you should instead, for example, declare a method:
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
And then in your configuration:
<bean id="myClass" class="MyClass">...</bean>
<bean id="myOtherClass" class="MyOtherClass">
<property name="myClass" ref="myClass"/>
</bean>
Spring will then automatically inject myClass into myOtherClass.
Declare everything in this way, and at the root of it all have something like:
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication is the most central class, and depends at least indirectly on every other service in your program. When bootstrapping, in your main method, you can call applicationContext.getBean("myApplication") but you should not need to call getBean() anywhere else!
Reasons to prefer Service Locator over Inversion of Control (IoC) are:
Service Locator is much, much easier for other people to following in your code. IoC is 'magic' but maintenance programmers must understand your convoluted Spring configurations and all the myriad of locations to figure out how you wired your objects.
IoC is terrible for debugging configuration problems. In certain classes of applications the application will not start when misconfigured and you may not get a chance to step through what is going on with a debugger.
IoC is primarily XML based (Annotations improve things but there is still a lot of XML out there). That means developers can't work on your program unless they know all the magic tags defined by Spring. It is not good enough to know Java anymore. This hinders less experience programmers (ie. it is actually poor design to use a more complicated solution when a simpler solution, such as Service Locator, will fulfill the same requirements). Plus, support for diagnosing XML problems is far weaker than support for Java problems.
Dependency injection is more suited to larger programs. Most of the time the additional complexity is not worth it.
Often Spring is used in case you "might want to change the implementation later". There are other ways of achieving this without the complexity of Spring IoC.
For web applications (Java EE WARs) the Spring context is effectively bound at compile time (unless you want operators to grub around the context in the exploded war). You can make Spring use property files, but with servlets property files will need to be at a pre-determined location, which means you can't deploy multiple servlets of the same time on the same box. You can use Spring with JNDI to change properties at servlet startup time, but if you are using JNDI for administrator-modifiable parameters the need for Spring itself lessens (since JNDI is effectively a Service Locator).
With Spring you can lose program Control if Spring is dispatching to your methods. This is convenient and works for many types of applications, but not all. You may need to control program flow when you need to create tasks (threads etc) during initialization or need modifiable resources that Spring didn't know about when the content was bound to your WAR.
Spring is very good for transaction management and has some advantages. It is just that IoC can be over-engineering in many situations and introduce unwarranted complexity for maintainers. Do not automatically use IoC without thinking of ways of not using it first.
It's true that including the class in application-context.xml avoids the need to use getBean. However, even that is actually unnecessary. If you are writing a standalone application and you DON'T want to include your driver class in application-context.xml, you can use the following code to have Spring autowire the driver's dependencies:
public class AutowireThisDriver {
private MySpringBean mySpringBean;
public static void main(String[] args) {
AutowireThisDriver atd = new AutowireThisDriver(); //get instance
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"/WEB-INF/applicationContext.xml"); //get Spring context
//the magic: auto-wire the instance with all its dependencies:
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
// code that uses mySpringBean ...
mySpringBean.doStuff() // no need to instantiate - thanks to Spring
}
public void setMySpringBean(MySpringBean bean) {
this.mySpringBean = bean;
}
}
I've needed to do this a couple of times when I have some sort of standalone class that needs to use some aspect of my app (eg for testing) but I don't want to include it in application-context because it is not actually part of the app. Note also that this avoids the need to look up the bean using a String name, which I've always thought was ugly.
One of the coolest benefits of using something like Spring is that you don't have to wire your objects together. Zeus's head splits open and your classes appear, fully formed with all of their dependencies created and wired-in, as needed. It's magical and fantastic.
The more you say ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed");, the less magic you're getting. Less code is almost always better. If your class really needed a ClassINeed bean, why didn't you just wire it in?
That said, something obviously needs to create the first object. There's nothing wrong with your main method acquiring a bean or two via getBean(), but you should avoid it because whenever you're using it, you're not really using all of the magic of Spring.
The motivation is to write code that doesn't depend explicitly on Spring. That way, if you choose to switch containers, you don't have to rewrite any code.
Think of the container as something is invisible to your code, magically providing for its needs, without being asked.
Dependency injection is a counterpoint to the "service locator" pattern. If you are going to lookup dependencies by name, you might as well get rid of the DI container and use something like JNDI.
Using #Autowired or ApplicationContext.getBean() is really the same thing. In both ways you get the bean that is configured in your context and in both ways your code depends on spring.
The only thing you should avoid is instantiating your ApplicationContext. Do this only once! In other words, a line like
ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");
should only be used once in your application.
One of Spring premises is avoid coupling. Define and use Interfaces, DI, AOP and avoid using ApplicationContext.getBean() :-)
One of the reasons is testability. Say you have this class:
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
#Component
class MyBean {
#Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
How can you test this bean? E.g. like this:
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
Easy, right?
While you still depend on Spring (due to the annotations) you can remove you dependency on spring without changing any code (only the annotation definitions) and the test developer does not need to know anything about how spring works (maybe he should anyway, but it allows to review and test the code separately from what spring does).
It is still possible to do the same when using the ApplicationContext. However then you need to mock ApplicationContext which is a huge interface. You either need a dummy implementation or you can use a mocking framework such as Mockito:
#Component
class MyBean {
#Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
This is quite a possibility, but I think most people would agree that the first option is more elegant and makes the test simpler.
The only option that is really a problem is this one:
#Component
class MyBean {
#Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
Testing this requires huge efforts or your bean is going to attempt to connect to stackoverflow on each test. And as soon as you have a network failure (or the admins at stackoverflow block you due to excessive access rate) you will have randomly failing tests.
So as a conclusion I would not say that using the ApplicationContext directly is automatically wrong and should be avoided at all costs. However if there are better options (and there are in most cases), then use the better options.
The idea is that you rely on dependency injection (inversion of control, or IoC). That is, your components are configured with the components they need. These dependencies are injected (via the constructor or setters) - you don't get then yourself.
ApplicationContext.getBean() requires you to name a bean explicitly within your component. Instead, by using IoC, your configuration can determine what component will be used.
This allows you to rewire your application with different component implementations easily, or configure objects for testing in a straightforward fashion by providing mocked variants (e.g. a mocked DAO so you don't hit a database during testing)
Others have pointed to the general problem (and are valid answers), but I'll just offer one additional comment: it's not that you should NEVER do it, but rather that do it as little as possible.
Usually this means that it is done exactly once: during bootstrapping. And then it's just to access the "root" bean, through which other dependencies can be resolved. This can be reusable code, like base servlet (if developing web apps).
There is another time when using getBean makes sense. If you're reconfiguring a system that already exists, where the dependencies are not explicitly called out in spring context files. You can start the process by putting in calls to getBean, so that you don't have to wire it all up at once. This way you can slowly build up your spring configuration putting each piece in place over time and getting the bits lined up properly. The calls to getBean will eventually be replaced, but as you understand the structure of the code, or lack there of, you can start the process of wiring more and more beans and using fewer and fewer calls to getBean.
I've only found two situations where getBean() was required:
Others have mentioned using getBean() in main() to fetch the "main" bean for a standalone program.
Another use I have made of getBean() are in situations where an interactive user configuration determines the bean makeup for a particular situation. So that, for instance, part of the boot system loops through a database table using getBean() with a scope='prototype' bean definition and then setting additional properties. Presumably, there is a UI that adjusts the database table that would be friendlier than attempting to (re)write the application context XML.
however, there are still cases where you need the service locator pattern.
for example, i have a controller bean, this controller might have some default service beans, which can be dependency injected by configuration.
while there could also be many additional or new services this controller can invoke now or later, which then need the service locator to retrieve the service beans.
You should to use: ConfigurableApplicationContext instead of for ApplicationContext

How to process a bean before factoryBean returns an instance?

I find it impossible to post-process a bean before factoryBean.getObject() is called. 'resultingBean' is a dependency of some bean that is initialized at the beginning, so that it is instantiated first. See I would need 'myBeanPostProcessor' to do something with 'myBean' before 'resultingBean' is constructed in 'MyFactoryBean'. Neither lazy-init nor depends-on helps. No matter what, 'MyFactoryBean.getObject()' is always called first.
<bean id="myBean" class="example.MyBean" />
<bean id="myBeanPostProcessor" class="example.MyBeanPostProcessor" />
<bean id="resultingBean" class="example.MyFactoryBean" depends-on="myBean"/>
Any idea how to deal with this? I chose BeanPostProcessor on purpose because this requirement should deal with setting up mocito mocks preceding junit #Before method...The problem is that setting up those mocks in #Before method is too late because you need to work with them at the time of context initialization.
There is not many ways how to do that, including ExecutionListeners, ContextLoaders, BeanFactoryPostprocessor, Runner and many others.
I'm using springockito that mocks my beans on the fly.
This is a little drawback of otherwise perfect spring test framework.
I don't really agree with using mocks like that (ie for integration tests) but I understand your problem.
You need to use the ApplicationContextAware interface which is called before InitializingBean, and BeanPostProcessor.
However Your Factory will always be called first so consider a different option like the new java style of configuration or refactor (as it seem you might have sort cyclical dependency)
Other than I need more info.
Not sure if I understood your issue well, but can't you simply create another context file - say test-override-context.xml and redefine the beans there, the last bean with the same name is that takes effect in the context.
in your test-override-context.xml file:
<import resource="my-base-resource.xml"/>
<bean id="myBean" class="MyMockedBean">

Get application components without #Autowired

How would you extract something prior 2.5 version from .xml config? It bothers me because if #Autowired is removed from my arsenal I would not really know what to do.
Say I want to use some DAO implementation.
In service class I usually write:
#Autowired
someDaoInterface generalDao;
Then I typically call
generalDao.someInterfaceMethod(someParam param);
How would I extract implementation from config in Spring 2.0 to use this method?
Is it as dumb as just: new ApplicationContext(pathToXml) and then use .getBean or there is other way?
Why do I ask for taking bean out from configuration file?
Because in Spring MVC how can you perform your logic without getting beans out from the application context.
If you have #Controller handler then you need to make calls to the service classes' methods? So they should be somehow retrieved from the context and the only way so far is using #Autowired? Then I would also want to populate Service classes as I stated in previous example with DAO classes and they also need to be retrieved from the application context, so I would be able to write logic for service classes themself. How would people do it in the past?
I see the #Autowired as the only mean of taking something out, not because it is convenient to wire automatically - I am perfectly ok with XML.
You still have option to wire it explicitely via property or constructor parameter. (Anyway, autowired is not going to work if there is ambiguity in your container )
Of course, you can use application context and getBean() in your java code, but it violates DI pattern and makes all the spring stuff useless. Purpose of DI is to decouple your business loginc from implementation details - it's not business logic it's how and where it dependencies come from. Dependencies are just there.
By using ApplicationContext.getBean() you are breaking this pattern, and introduce dependency to:
spring itself
your configuration names
After you done this, you can as well drop use of DI and spring because you just voided all the advandages DI is providing to you. (BTW, #Autowired also introduces dependency to spring, and violates DI pattern, it also implies that there is only one instance available)
Also, answer is: in ideal case there shall be no reference to spring in your code at all.
No imports, no annotations - just interfaces of collaborating entities.

How can I run a method after the Spring singleton initialization is complete?

Using Spring 3.0.x, I'm running into an issue where a Bean init-method is running, and as part of it fetches some information, and then in another thread (original init() thread waits on the other threads to complete) tries to get one or more Beans based on that information retrieve. Problem is, these other Beans are singleton as well and haven't been initialized yet. There's a synchronized() block down in DefaultSingletonBeanRegistry in the getSingleton() methods.
The problem arises that I'm trying to get/initialize a Bean while I'm currently initializing a Bean, so I get stuck with the main thread in the init() method, and another thread trying to get another singleton Bean, and is blocked because the 1st thread has the lock.
So, the way I see it, I have 2 options:
1) Get Spring to run a method AFTER the singleton has been fully created that performs the actual data fetch and processing
2) Come up with message passing to which will give the data back to the main thread to then process them all within it since it already has the monitor lock
Thoughts? Ideas? How would I get #1 to work?
Have you tried implementing the InitializingBean interface
class MyBean implements InitializingBean{
#Override
public void afterPropertiesSet(){
// fetch information, etc
}
}
According to the docs:
Interface to be implemented by beans that need to react once all their properties have been > set by a BeanFactory: for example, to perform custom initialization...
You could implement the Lifecycle interface. The lifecycle callbacks happen when start()/stop() is called on the enclosing subclass of AbstractApplicationContext, which happens after all singleton beans of have been initialized (dependencies injected, and init methods called). The lifecycle callbacks also follow dependency order just like initialization does.
You don't mention what kind of configuration you are using (annotation based or XML based), but in XML bean configuration, you can use a depends-on attribute to ensure that the sequence of beans that you need instantiated are done in the proper order.
For example, if you have two beans:
<bean id="bean1" class="my.package.class" />
<bean id="bean2" class="my.package.class2" />
<bean id="bean3" class="my.package.class3" depends-on"bean1, bean2" />
In this case, bean1 and bean2 will be instantiated in unconfirmed order. Spring attempts to instantiate based on the order of the XML file, but there is no guarantee to that. However, bean3 is guaranteed not to be instantiated prior to bean1 and bean2 being instantiated.
I do not know if this will rectify your race condition, but hopefully it should help.
Worst case scenario, you can always instantiate all the beans, and once instantiated, you can use FactoryMethodInvokingBean to call a static method once the bean is instantiated. Once again, make sure you use depends-on to ensure that the FactoryMethodInvokingBean is called once the singleton bean is instantiated.
If anyone is looking for a more current answer that is not tied to a specific framework (like Spring), Java provides the #PostConstruct annotation that accomplishes the same thing. Using annotation-based config with Spring will recognize this annotation and execute a method annotated with #PostConstruct after the managed bean is initialized.
Perks include:
You're removing the Spring dependency from your class
You can name the method whatever you want
Why use #PostConstruct?
Some practical examples

ApplicationContext and beans retrieval

I'm reading Spring documentation and I stumbled across a piece of text that made me ponder a bit.
You use getBean() to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but ideally your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all, and thus no dependency on Spring APIs at all.
Well, I configured beans in my xml file. But I still need retrieve them when in need. How can I do that without getBean() method? The more detailed explanation, the better.
You need some way to retrieve Spring beans when you want to access them from classes that were not created by Spring, e.g. the main class in a command line program, and you use the getBean methods for that.
But Spring beans themselves do seldom need this feature, because it is Spring's responsibility to provide the other beans that are required, via constructor arguments or setter methods (this is the basic idea behind dependency injection).
The basic idea is "don't call us, we'll call you", meaning that your code doesn't ask Spring IOC (Inversion of Control)-container for the beans, but rather the container injects the beans into your code. The injections are configured either using xml-configuration file(s) or via annotations. For more details, see for example this and this. Also I'd recommend reading the whole chapter 3 from the reference manual (as you probably are doing).
The ApplicationContext-interface still makes it possible to ask for beans programmatically, which might be needed in some special cases, for example when integrating with some other framework or such.
Some time ago I wrote some generic parser that could handle different input file formats.
class XmlFormat extends Format {
// format stuff
// ...
}
class Parser {
Format format;
public Parser(Format format) {
this.format = format;
}
// parsing goes here
// ...
}
Next I told Spring which format description was to use.
(Disclaimer: Your Spring config may have a very different style.)
<bean id="forma1" class="com.mycompany.XmlFormat" />
<bean id="parser" class="com.mycompany.Parser">
<constructor-arg ref="format1">
</bean>
So now when I wanted Spring to give me a Parser, it injected the XmlFormat into the constructor for me.

Categories

Resources