Create servlet context without autowiring in spring - java

I have a singleton class and one its private members is ServletContext object.
I made it singleton to remove spring dependency since I am trying to write in pure java code.
public class Utils {
private static Utils utils = null;
public Utils() {
// Exists only to defeat instantiation.
}
public synchronized static Utils getInstance() {
if (utils == null) {
utils = new Utils();
}
return utils;
}
#Autowired
private ServletContext servletContext;
public void makeUtils() {
// output csv path
String outputFile = servletContext.getRealPath("/util");
}
}
But here servletContext will be null because I am creating the object of Utils class wherever I needed manually. Not by using #Autowired. So spring is not injecting the dependency. How can I solve this.

#Autowired is a spring annotation.
If you want something to happen in response to that annotation, then you need to use spring. If you want to remove the dependency on spring, then you can't use Autowired. You need to pick one - are you depending on spring for your wiring, or not?
Some solutions you could follow:
Using Spring
Make Utils a spring bean and inject it
Put Utils into your spring context (bean factory) and then inject it (using #Autowired, or another wiring strategy) into every other class that wants to use it.
Make Utils a spring bean and look it up.
There's really not much reason to do it this way, but if you want, you can get access to your spring bean factory (probably via the ApplicationContext) and lookup a bean by type using BeanFactory.getBean(Class<T>)
Use Spring to autowire an existing Utils object
Again, there's not many good reasons to do this, but if you have an instance of AutowireCapableBeanFactory (which you can get via ApplicationContext) then you can call autowireBean(Object existingBean) to get spring to wire up your #Autowired fields.
Note: My method/class references are from Spring 3.2 because it's what's open in my IDE right now. You may need to make adjustments if you have a different spring version)
Without Spring
Instantiate Utils within a Servlet (or Listener)
Create a configure method on Utils that takes the ServletContext.
Inside a Servlet (or a ServletContextListener) call that configure method to set the servletContext field on Utils.
Store a static global ServletContext
Create an object like ServletContextHolder that has a static field on which you can store the ServletContext
Inside a Servlet (or a ServletContextListener) call the setContext method on that holder set the servletContext field.
Inside Utils call ServletContextHolder.getContext()

Related

how to initialize a bean in spring container once and use it everywhere

actually i'm using spring for developing a web application, the problem i'm facing is that i'm initializing a bean as soon as the spring container is getting loaded, now i have to use that bean in different parts of my program.
constraints that i have
1. i can get application context everywhere and get that bean but according to my problem i should get that bean without writing that redundant code again and again.so is there any way by which i can initialize that bean and use it directly everywhere in my program.
If you already initialized your bean you can get access to it via #Autowired from each Component in your Spring Application.
private SomeClass myBean;
#Autowired
public void setMyBean(SomeClass myBean){
this.myBean =myBean;
}
Or just:
#Autowired
private SomeClass myBean;
I prefer the first method, looks fancier in my eyes.
You should not get your bean from the context directly, instead you should #Autowire them and let Spring inject it for you.
Here’s an example of two dependencies injected via constructor:
#Component
public class Car {
private final Engine engine;
private final Transmission transmission;
#Autowired
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
}
}
Note that your class must be a Spring Component itself in order for the injection to occur.
There are actually three types of dependency injection in Spring: constructor, field and setter injection. Spring team recommends using the constructor based approach, and this post brings very nice arguments to this point: https://blog.marcnuri.com/field-injection-is-not-recommended/
You can refer to this link for more information on constructor-based injection: https://www.baeldung.com/constructor-injection-in-spring

How do I add a bean to Spring context in my library without breaking consumers who have their own instance of that bean?

I have a library which produces beans into a Spring context for use by clients. The beans I produce are configured by Spring. I need to add a new bean to my context in order to satisfy a dependency of a new bean I'm publishing. However, I believe some of my clients already have an instance of this bean and are autowiring it by type. So I have something like this:
// Code in my Library
#Component
public class PublicUtilityClass {
// This is all new code in my library
private NewDependency newDependency;
public void newCapability() {
newDependency.doNewThing();
}
#AutoWired
public void setNewDependency(NewDependency newDependency) {
this.newDependency = newDependency;
}
// Other library code omitted.
}
How can I use Spring to instantiate NewDependency and inject it into PublicUtilityClass without impacting customers who already have a NewDependency bean in their context?
You should look at #Qualifier annotation. Qualifier allows you to have multiple instance of your bean

Why does adding Spring DI into a Jersey 1.19.1 make my resource a singleton?

My goal in this entire endeavor is to try and inject a data source into a resource that can change at runtime. I am trying to avoid having to bloat the logic inside my resource if at all possible.
This is a legacy application with Jersey 1.19.1 using Spring 4.1.9.RELEASE (spring-aop, spring-beans, spring-context, spring-core, spring-expression, spring-web)
So here is my example resource:
#Path("/test)
public class TestResource {
public TestResource(){
System.out.println("Constructor Hit");
}
}
If I run hit this resource I get the following output
...request...
Constructor Hit
...request...
Constructor hit
So, the resource is created everytime there is a request, great!
Now, I want to use spring to inject a bean into this resource, so I get the following class.
#Path("/test)
#Component
public class TestResource {
#Inject
public TestResource(MyBean test){
System.out.println("Constructor Hit");
}
}
Now I get the following output
Constructor hit
...request...
...request...
The resource is only created once (I'm guessing at Spring application creation time).
Is there a way to fix this? I believe it is because I annotate with #Component but I can't seem to get the injection part without that.
Spring's default scope is singleton. when you call prototype class in singleton, spring DI inject prototype class just once at instantiate time.
read this issue if you want the singleton bean get a new instance of the prototype bean at runtime.

Autowire of prototype bean into prototype bean?

I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.

Injecting beans into a class outside the Spring managed context

I'm an end-user of one of my company's products. It is not very suitable for integration into Spring, however I am able to get a handle on the context and retrieve the required bean by name. However, I would still like to know if it was possible to inject a bean into this class, even though the class is not managed by Spring itself.
Clarification: The same application which is managing the lifecycle of some class MyClass, is also managing the lifecycle of the Spring context. Spring does not have any knowledge of the instance of MyClass, and I would like to some how provide the instance to the context, but cannot create the instance in the context itself.
You can do this:
ApplicationContext ctx = ...
YourClass someBeanNotCreatedBySpring = ...
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(
someBeanNotCreatedBySpring,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
You can use #Autowired and so on within YourClass to specify fields to be injected etc.
One way to bring a bean into Spring despite its manufacture being external is to use a helper class marked as a #Configuration bean that has a method (marked with #Bean) that actually makes the instance and hands it back through Spring (which does its property injection and proxy generation at that point).
I'm not quite sure what scope you need; with prototype, you'll get a fresh bean in each place.
#Configuration
public class FooBarMaker {
#Bean(autowire = Autowire.BY_TYPE)
#Scope("prototype")
public FooBar makeAFooBar() {
// You probably need to do some more work in here, I imagine
return new FooBar();
}
}
You can inject properties required for manufacture into the #Configuration bean. (I use this to create instances of an interface where the name of the class to instantiate is defined at runtime.)
suppose that u have the following dependency chain:
A --> B --> C --> x --> y -- > Z
A, B, C are spring managed beans (constructed and manged by spring framework)
x, y are really simple POJOs that constructed by your application, without spring assistance
now if you want that y will get a reference to Z using spring that you need to have a 'handle' to the spring ApplicationContext
one way to do it is to implement ApplicationContextAware interface . In this case I would suggest that either A, B or C will implement this interface and will store the applicationContext reference in a static member.
so lets take Class C for example:
class C implmenets ApplicationContextAware{
public static ApplicationContex ac;
void setApplicationContext(ApplicationContext applicationContext) {
ac = applicationContext;
}
.............
}
now, in class y you should have:
(Z)(C.ac.getBean("classZ")).doSomething()
HTH -- Yonatan
Another way to do this is to us use AspectJ. This is the recommended way of injection Spring beans into non-managed objects that are created with the new operator. See this for details:
http://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html
Searching endless combos of autowire inject spring bean into pojo applicationcontextaware beanaware etc circled me back here but this didnt provide a complete enough solution for me.
This is a much better implementation/tutorial of this IMO:
I hope it helps everyone like it finally helped me.
Accessing Spring Beans from outside Spring Context
Be careful that in oldest version of Spring, there is thread-safe problem with bean factory http://jira.springframework.org/browse/SPR-4672
If you want to create an object outside the Spring context, and make that object available for injection into other beans that are in the Spring context, you can follow the steps in this article.
Basically, you create a parent application context and push your external object into this parent context as a singleton. Then you create you main application context (for example, from xml files), with the parent application context as its parent.
Object externalObject = ...
GenericApplicationContext parent = new StaticApplicationContext();
parent.getBeanFactory().registerSingleton( "externalObject", externalObject );
parent.refresh();
ApplicationContext appContext = new ClassPathXmlApplicationContext( ... , parent);
From a Spring configuration class, set a static field on the non-Spring class that needs the beans.
I have an example in my answer to a Liquibase question: https://stackoverflow.com/a/71191546/5499391

Categories

Resources