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

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.

Related

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.

Using managed beans and injection in a J2EE application in Websphere Liberty Profile

I've got a J2EE app I'm converting to run on Websphere Liberty Profile (WLP). I'm specifically trying to get my EJB references injected.
I've got my WLP server configured with the ejb-lite, managed-beans, and cdi features. I've placed a beans.xml file in my WEB-INF directory, and annotated an action class as a #ManagedBean, and added a #PostConstruct and #PreRemove method with logging to see if things are working. I never see my #PostConstruct and #PreRemove methods called
I've tried a few things to get the injection to work, including #Inject and various flavors of #EJB with different arguments. Nothing seems to work. I don't get any errors, but there's no indication that any annotation processing is taking place. When I do a straight JNDI lookup to get the ejb, it works fine.
Everything I've read indicates that this should work, but I can't figure out why it doesn't.
#covener was correct...the bean creation wasn't happening via the container in the way I thought, so no dependency injection was taking place. I was misled by the fact that I would sometimes get errors from the container if I made an mistake in my annotation for the the #Inject or #EJB tags. That told me that the classes were being scanned and processed, it was only happening as part of a preprocess step by the openwebbeans container in WebSphere Liberty Profile. All of the docs I could find online were pretty vague about the requirements, but I think the key is your class has to be created directly by the container, instead of created by a class created by the container.
So even though my classes are correctly annotated, and are actually being processed for annotations by the container, the circumstances of my app are such that the classes aren't created in a managed way by the container (and in fact can't be), so they never get handled for CDI.
#ManagedBean is a JSF annotation you shouldn't use in CDI context. Your bean class should be concrete, have no constructor or a default constructor with no parameter.
#PostConstruct and #PreDestroy(not #PreRemove) should be put on method with no arguments.
If your problem persist try to update your question with more information (class, server log, etc...)

Spring annotations conflicts with my design guidelines

Overview
Using
Spring 3.0.1 (annotation configuration)
Current configuration is using CGLib as proxy creator but this is not my preference
Transactions are annotation configured without any special settings
All configuration is done with annotations (#Service, #Transactional, #ManagedResource, #Inject, etc.)
Hibernate 3.5 (entities are annotated with javax.persistence)
Guidelines highlights
Every bean annotated with #Repository or #Service must have an interface
Constructor DI (when re-configuration isn't required)
Constructor has default visibility (Foo(Bar bar) {...})
Bean fields are final (when re-configuration isn't required)
Leads to no default constructor
Implementations are default visible with final modifier (final class Foo)
The Problem
CGLib can't proxy final classes
CGLib requires default (empty) constructor
Some services are required to be exposed via JMX
MBean exporter can't work unless proxied by CGLib
Some #Transactional #Services are accessed via facade service which requires more than one service to include in the facade transaction (e.g. Observer service over 2 application components)
Some interfaces have more than one implementation (which currently distinguished by #Qualifier)
Future guideline (or nice to have feature) - each application module will have beanRefContext.xml file to configure its internal application context
When I used to work with XML configuration I was able to enforce all the guidelines I presented above, but when switching to annotations it seems like Spring is misbehaving.
Developers in my group prefer annotation configuration (I seems easier to wire and write new code), but I've noticed all kind of "hacks" they introduce to the code to prevent from dealing with Spring application context failures.
The Question(s)
Are there best practices I should follow when using annotation configuration?
When using more than one implementation per interface (trying to reduce the use of #Primary or #Qualifier)
When using #Transactional
When using #ManagedResource
When using a combination of the above
Is there a way of stop working with CGLib, keep the annotation configuration and still be able to export my MBeans with annotations?
What is the suitable implementation for keeping most (preferably, all) of my guidelines?
I came up with the following solution (to questions #2 and #3) to be able to enforce my design guidelines and keep using annotation based configuration:
Each dependent project (Maven module) has it's own ApplicationContext
Every dependent project application context is defined in beanRefContext.xml
These application contexts are loaded in hierarchy using Spring context hierarchy mechanism.
This step is actually not fully supported by Spring and requires additional work
Since my application is layered, I could disable CGLib on all my modules besides the JMX layer (I can live with it :-) ).
The above steps also enabled me to reduce the execution time of Spring aware tests (every module loaded only a sub-set of beans).
As a practical guideline (for question #1), if an interface has more than one implementation, I place #Primary on the widely used one and other clients, requiring another implementation, wire the bean using #Qualifier.
Answer to point 2)
You could use AspectJ instead of CGLib.

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

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.

How to use #Autowired with Java-based config?

I am using Java-based Spring configuration in my project, specifying bean construction in #Bean-annotated methods in #Configuration. Recently, Recently, I've started to think that maybe it would've been better to use #Autowired to remove all non-important beans from #Configuration, leaving only small "root" set of them (key services and technical beans like those of Spring MVC).
Unfortunately, it seems that Spring can notice implementations for #Autowired dependencies only if they are inside component-scanned package which I cannot do without resorting to some XML.
Is there any way to use #Autowired with Java-based configuration without explicitly specifying each bean?
If I understand you correctly, you're expecting Spring to auto-discover the DaoImpl class based on the autowired dependency on the Dao interface.
This isn't going to happen - you either need to use component scanning, or you need to explicitly declare the bean, either as <bean> or #Bean.
The reason for this is that Java provides no mechanism to discover classes which implement a given interface, the classloader just doesn't work that way.
If you are implementing the Idao via dao and you are looking to #Autowire that dependency into your reference var... you need to first:
define the bean so you (in Java Based Config) simply return the impl class to the interface. The bean name is that of your method name.
When you autowire this, it will search for a matching name between your reference variable you are looking to autowire and your declaration.
THEN you will be fine. Hope this helps.

Categories

Resources