Access application context from BundleContextAware class - spring

I have created an osgi bundle from an existing legacy war. The app has a class that implements the spring interface ApplicationContextAware, it then uses the context to programmatically get beans (not sure why but this needs refactoring eventually). The app now uses OsgiBundleXmlApplicationContext, but I believe that there is an issue with using this whereby the setApplicationContext method does not get called in any classes implementing ApplicationContextAware, so now the context in this class is always null.
So as a workaround I have implemented BundleContextAware so that I can get a reference to the published context and get access to the beans that way. This works ok however the only bean on the context is warDeployer (should mention that I am using the spring dm bundle spring-extender to deploy the war). The bundle present on the context is my bundle so I cannot see why the context that I am getting has none of my beans on it. The code I have to get the application context is:
ServiceReference ref = bundleContext.getServiceReference(ApplicationContext.class.getName());
applicationContext = (OsgiBundleXmlApplicationContext) bundleContext.getService(ref);
I can see in the logs that much of my context is getting created so I can't see why they are not on the context I am getting.
Can anyone advise as to what is wrong? I understand that this approach is a bit hacky, but it's temporary until the existing code is refactored.
Thanks in advance.
Barry

I believe that the ApplicationContext service is registered asynchronously by the Spring-DM extender. So you probably have a race condition, i.e. asking for the service just before it is actually registered.
You could introduce a delay but then you're very deep into nasty hack territory. It would be better to work out why the setApplicationContext method on the ApplicationContextAware beans is not being set. You should try raising this is a bug against Spring-DM or asking in the Spring-DM Google Group.

Related

Debugging with Java/Spring's #Autowired on Eclipse

I have picked up a project that uses #Autowired and dependency injection a lot. People have been saying all the nice things about them. It seems kind of like a magic.
I am new to Spring injection and #Autowired. My first glance of #Autowired is good, but when I work with them on Eclipse, I have difficulties tracing them around when debugging.
For example, is there an easy way in Eclipse that I can see where and how an #Autowired bean is initiated? How do I know if it is initiated correctly the way I want? Is there a way to trace the sequence of it being called/accessed?
Anybody has any tips or comments that may help me to debug #Autowired bean easier on Eclipse?
When a Spring application starts, it first creates instances of beans, either by scanning for annotations, or processing the XML Spring context definition. Some of those beans have to be created in a specific order, like if they use constructor injection. Once beans are created, wiring those beans together can happen.
If you want to see what happens when a bean is constructed, set a breakpoint in the constructors of the class. Look down the stacktrace to see what caused it to be constructed.

What is the best place in SpringBoot application to initialize business logic?

I want to initialize some business logic (e.g. send some messages to a message broker) in a Spring Boot application after context is created and beans (singletons) are initialized - what is the "most correct" place for it?
From my perspective the candidates are:
Implement ApplicationListener + listen for ContextStartedEvent
ApplicationRunner's OR CommandLineRunner's run() method
#PostConstruct of a particular bean (I don't this method, but have seen sometimes in colleagues' code - because I need to be sure all beans are created, initialized, customized, set up, etc. and I don't wanna play with beans load order)
I understand that in general, in MVC web application the place for business logic is #Service, but I need to call it immediately after the start of my application, so what's the best way to do that?
I would go with #EventListener. Like you said there are different ways to achieve this. I will give my opinion on your numbers
ApplicationListener called 3 times. No need to listen this one. This maybe usefull if you are doing something close to tomcat.
ApplicationRunner,CommandLineRunner is called after all bean initialization. This can be useful.
#PostConstruct you can get null beans if you are working with other components.
I prepared a small example to use all these in one application and print some logs but I could not put them here. spring log looks ugly here. anyway my suggestion is here if you dont have any dependency to other beans this looks nicest. if there are dependencies then you can use ApplicationListener which was the last logged in my example.

using/importing/injecting spring-managed class into non-spring class

Is there a way to inject/import spring-managed class into a legacy code or non-spring class?
I am working on a spring project, but we have this legacy code that needs access to a spring managed class (specifically a jparepsository implementation class). Is this possible?
Sorry, I am a newbie in the Spring framework. Any help/advice will be greatly appreciated. Thanks :)
You can always load an application context up in your code. It's a simple matter of doing something like this:
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
You'll have access to all the beans created there via the getBean() function. This may be sufficient for you. However, you won't be accessing the same context as other parts of your application, you'll have a copy. So if you have stateful beans in your application context the "unmanaged" code won't see the same state.
if you're talking about a web application, then you can use the WebApplicationContextUtils to access the same context as the rest of the web applicatiom.
WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
Since you have access to the legacy code, what prevents you from rewriting it to be spring managed, or at leas to be ApplicationContextAware?

Grails 2.3 strange plug-in eager loading behavior

I've just added a custom local plug-in (via 'grails.plugin.location...' build config declaration) to a grails 2.3 project. As soon as I add the plug-in and try to run my application I see a strange behavior whereby all of the beans in my main application suddenly try to eagerload across the board. I.e. if I have:
class FooService {
BarService barService
}
class BarService {
FooService fooService
}
Then the application cannot start. There is no code being executed in FooService or BarService at init time that should cause the Spring context to need to unwrap the either fooService or barService instance but that behavior seems to be happening anyway. In the end the application init fails with an exception like:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'fooService': org.springframework.beans.factory.FactoryBeanNotInitializedException: FactoryBean is not fully initialized yet
As the fooService requires the barService, which requires the fooService which is still being created.
As soon as I remove the dependency on the custom plug-in then the problem stops. Obviously something either in the plugin or about the plugin (meta data or something) is causing this behavior but I can't figure out what exactly.
Rather than a solution I think what I am looking for here is some trouble-shooting techniques or information leading me to understand why this eagerloading behavior is occurring. I just don't know what the right hooks/configs are that will let me get in the head of the Spring context initialization mechanism.
I found the answer to my question buried deep in the comments of this other SO question: Grails service using a method from another service
Basically my plugin introduced the hibernate plug-in into my project and therefore also introduced transactional-by-default services. This transactional bootstrapping was causing the eager load of all dependencies and thus my circular dependency problem.
The fix was to, at least for now, mark the circularly dependent services as non-transactional. Of course in the future if I need those services to be transactional it seems I will need to re-architect my service setup.

How can I access Spring bean from Message-driven bean in JBoss AS 7

I want to make a call to a Spring bean (a #Component) from my message-driven bean (MDB) but have problems getting a reference to it. I've tried with a class implementing org.springframework.context.ApplicationContextAware which stores the Spring ApplicationContext in a static field in a class MyAppContext. The static field in MyAppContext is then accessed from the MDB. But MyAppContext is loaded from different classloaders. The Spring application context is correctly set in the web module classloader context, but in the MDB's classloader context, it's null.
Can I somehow instruct JBoss to use the same classloader for the web app and the MDB?
Or is there a better way than storing the Spring application context in a static field?
Thanks for any advice!
A static holder for the context is not really a good idea. To make your beans available to other applications in a Java EE environment, you should consider making use of JNDI.
Unfortunately, there is no plain JNDI exporter available out of the box, but it's fairly easy to write one yourself, as shown in this blog post: http://maestro-lab.blogspot.ro/2009/01/how-to-export-spring-managed-bean-to.html
There is however a JndiRmiServiceExporter that you may want to look at.
Once your beans are bound to names in JNDI, they can be referenced using standard CDI in your message bean without worrying about class loading issues.
Why not use "ClassPathXmlApplicationContext" to load and look up for the Spring bean you require in your MBean?

Resources