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

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?

Related

spring boot servlet context vs application context

I Come from years with Spring MVC, I'm trying to understand some key differences with Spring boot.
With Spring MVC I used to make a very clear distinction between application context and servlet context(s).
With Spring boot it looks like the servlet context has been pretty much deprecated and all the beans created by means of autoconfig mechanism live in the app context.
you can still create your servlet context of course, you have just to keep in mind the autoconfig is using application context.
so for example one implication of this is that #RestControllers and #Controllers live in the application context and the Spring Boot autoconfig servlet dispatchers will use any #RestController or #Controller annotated beans in the app context.
Can you help me confirm on this or make me understand what I'm missing here ?
In spring-springMVC system, there are two containers as your mentioned. For springboot-springMVC, debug in your controller and service with implementing ApplicationContextAware
they use the same global applicationContext
org.springframework.boot.web.servlet.contextAnnotationConfigServletWebServerApplicationContext

When and where must I initialize the spring context?

I'm a noob when using Spring and I have a doubt.
When and where must I initialize the spring context?
Right now I am initializing the context when I'm going to use something like a properties file:
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("myContext.xml");
But I have read that the Spring context must be initialized in the entry point of my program (Main.java) and pass it as argument in the necessary methods.
Is this true?
As #MarounMaroun said, it really depends on what are you trying to do.
When people use Spring they usually build the entire application to take advantage of what Spring has to offer. That is to say, they put everything in the Spring context, configure it, and let it wire all the things together when starting. So in order to be useful, the application needs to load the Spring context before doing anything else.
For a standalone application you do the initialization in the main method.
When main is called, you first initialize the Spring context, and once the context is fully loaded you retain a reference to it and make it available where needed.
If it makes sense to initialize the Spring context at a later time or in another class you can do that too, but as I said, most applications need the context initialized to be able to function so that's why they initialize it as early as possible, in the main method, and that's probably the recommendation you have read.
If you are talking about a web application, you should do it web.xml
Loading context in Spring using web.xml
If it's a test, things are different:
spring junit load application context for tests
In both cases, you don't need an explicit main.java

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?

CDI Bean accessing Spring beans?

I know this sounds strange, mixing CDI (Weld) and Spring for the controller.
But imagine this situation :
With CDI, i can make use of the #ConversationScoped, which is one of my requirement (And so far i dont know whether i can use spring for this kind of scope, because if i can, i could just replace Weld with Spring, with the el-resolver in faces-config.xml)
My services objects(#Service) along with the DAOs(#Repository) are to be managed by Spring
Now one question arise is that, inside my controller, how can i access my service object ?
Something like this wouldnt work i think :
#Named
#ConversationScoped
public class MyBean {
#Named
private SomeOtherBeanManagedByCDI myOtherBean; // this will work
#Autowired
private MySpringBean mySpringBean; // dont think that this will work
....
}
Any ideas on how to make use of spring beans inside a cdi bean ? Thank you !
update
I've just tested the solution from this article, and so far it works fine, and i feel relieved.
Thank you !
Rick Hightower wrote a nice Extension library which supports to inject Spring beans into CDI beans and vice versa:
http://rick-hightower.blogspot.com/2011/04/cdi-and-spring-living-in-harmony.html
There is still a good accepted answer and some good edits in the OP, but I think there still is time to point out the Seam Spring module.
Also, if you're trying to manage state across a series of pages, and want the effective of conversation management for Struts or JSF or Spring MVC, Spring Web Flow provides just what you need, complete with flow-scoped beans that live for the duration of a flow, more or less equivalent to a conversation in Seam / CDI. If you want a more long lived flow managment solution, the Activiti SPring module makes it dead simple to configure some beans that live for the duration of the process scope, akin to the functionality that Seam had for jBPM.

Access application context from BundleContextAware class

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.

Resources