Spring beans with runtime initialization parameters - spring

I have a class which needs
Dependency injection for various beans it uses
Runtime parameters for initialization
The class would look something similar to this
public class Validator {
#Autowired
private ServiceA serviceA;
#Autowired
private ServiceB serviceB;
private String s;
private ClassA a;
private ClassB b;
public void initialize(String s, ClassA a, ClassB b) {
this.s = s;
this.a = a;
this.b = b;
}
public void performTaskA() {
//use serviceA, serviceB, s, a and b
}
public void performTaskB() {
//use serviceA, serviceB, s, a and b
}
public void performTaskC() {
//use serviceA, serviceB, s, a and b
}
}
What are various options through which I can define the above class as spring bean (to take the advantage of dependency injection) and also make sure that the caller calls initialize() before calling any performTask*() methods?
Note - I am aware of Object getBean(String name, Object... args) throws BeansException; but it doesn't look good since we would loose type safety. Any other suggestions?
Update -
The solution mentioned here with lookup method injection is a nice option. Until it is implemented in spring, what's your opinion on the below alternative of using inner classes
public class MyService {
private ServiceA serviceA;
private ServiceB serviceB;
public class DataClass {
private Integer counter;
public DataClass(Integer counter) {
this.counter = counter;
}
public Integer performActionAndGetCount() {
serviceB.performAction();
return this.counter++;
}
}
}
//client module
MyService service = beanFactory.getBean("myService");
MyService.DataClass dataClass = service.new DataClass(1);
Any drawbacks of this approach?

Use component,service or repository annotation to annotate your class. This would enable your class to be considered as a spring bean and you can then use dependency injection and runtime initialization.
Make sure in your {dispatcher-servlet}.xml(replace the name in {} to the name you have given your dispatcher servlet in web.xml} file you have written this line

This can be accomplished using a combination of scope="prototype" and a <lookup-method>.
First, define the class you want to parameterize as a bean with scope="prototype". This will cause the context to generate a new instance every time the bean is requested.
<bean class="com.example.Validator" scope="prototype"/>
Then, define a "factory class" that will wrap the generation and initialization of new objects.
<bean class="com.example.ValidatorFactory">
<lookup-method name="newValidator"/>
</bean>
This class would look like this:
public class ValidatorFactory {
public Validator createValidator(String str, Class<?> classA, Class<?> classB) {
Validator v = newValidator();
v.initialize(str, classA, classB);
return v;
}
protected void newValidator() {
// Spring will implement this via AOP
}
}
This forces clients to go through a routine that will call initialize() while still loading beans via the Spring context.

I am not so clear about your requirement. But I think #PostConstruct annotated method can come to your rescue. You can find more details about #PostConstruct annotation here.
Hope this helps you. Cheers.

Related

How can I qualify an autowired property with a variable

I am working on a Spring application and for one of my scenarios, I had to write two implementations of a Service class. I would like to know how to autowire this in a service layer based on service id at runtime.
#Autowired
ProductPricing accessProduct;
public static void main(String args[])
{
long productId = serviceDao.getService(site.getSiteID()).getServiceId();
accessProduct.calculatePrice(pricingParam)
}
public class PricingManager1 implements ProductPricing
{
public void calculatePrice(Parmeter pricingParam) {}
}
public class PricingManager2 implements ProductPricing
{
public void calculatePrice(Parmeter pricingParam) {}
}
Now depending on the productId, either the method on PricingManager1 or PricingManager2 will be called. How to achieve the same dynamically? If I autowire the Service classes with qualifier, is there any way we can pass runtime productId as qulifier in main class?
You can achieve the expected output by using #Service and then getting the bean from spring context object in your main() as shown below:
Service Classes:
#Service("pricingManager1")
public class PricingManager1 implements ProductPricing
{
public void calculatePrice(Parmeter pricingParam) {}
}
#Service("pricingManager1")
public class PricingManager2 implements ProductPricing
{
public void calculatePrice(Parmeter pricingParam) {}
}
Main Class:
//No Autowiring
public static void main(String args[])
{
long productId = serviceDao.getService(site.getSiteID()).getServiceId();
//get the spring context object
//get the bean from context
if(productId == condition) {
beanContext.getBean("pricingManager1").calculatePrice(pricingParam)
} else {
beanContext.getBean("pricingManager2").calculatePrice(pricingParam)
}
}
If you are using Spring Boot, you can achieve this by using #ConditionalOnExpression annotation and SpEL along with #Bean.
#ConditionalOnExpression("#{this.productId == 999}")
If you are not using Spring Boot, use #Conditional from Spring 4, but this will need more effort to get the same result.

Spring Java Config reference in bean constructor to get other bean in constructed class

I've seen one of the program where MyConfig(Spring Configuration file) is being referenced in constructor of one of the bean in order to get other bean defined in MyConfig.
I am not sure about this kind of configuration. I can see cyclic reference in this kind of code, though it is working fine but I am not able to understand the flow. How it is working. Below is the replica of that code -
#Configuration
public class MyConfig {
#Bean(name="a")
#Scope("prototype")
public A getA() {
return new A();
}
#Bean(name="b")
#Scope("prototype")
public B getB() {
return new B();
}
#Bean(name="c")
#Scope("prototype")
public C getC() {
return new C();
}
#Bean(name="queueListener")
#Scope("singleton")
public Queue getQueue() {
return new Queue(MyConfig config);
}
}
Here is my Queue class -
public class Queue implements MessageListener{
private MyConfig config;
public Q(MyConfig config) {
this.config = config;
}
#Override
public void onMessage() {
createC();
}
public void createC() {
C cObj = config.getC();
cObj.setConfig(config);
cObj.performTask();
}
}
The class is "C" look like this-
public class C{
private transient MyConfig config;
private MyConfig config;
public C() {
}
public void setConfig(MyConfig config) {
this.config = config;
}
public MyConfig getConfig() {
return config;
}
public void performTask() {
A a = config.getA(); // Is it right way to get bean?
B b = config.getB();
}
}
So my question is that is it right way to get bean in another bean?
Will the return object really be spring bean object or simple java class object?
I can see cyclic reference in above code cause When instance of Queue class will be created inside MyConfig will take instance/reference of MyConfig.
Will this create cyclic reference?
My Architect has suggested me above approach instead of autoWiring Application context in both classes Queue and class "C". According to architect context is very heavy and it is not best practice.
What will be the execution cycle or call hierarchy when bean Queue is getting created?
It would be very much helpful to understand the working of above code.
It is a really bad idea to inject the configuration instance into a specific bean. It complicates your code and makes it inconvenient for testing because for testing Queue instance you should somehow mock the whole configuration.
If you want to inject a prototype bean to the singleton you can use a technique described here :
Howto generate prototype objects with in a singleton bean using spring java configurations
Please see example at Spring Boot #Autowired creating instances on a runtime
You can see how to use singleton and prototypes right way

Spring AOP proxy and interface implementation

I'm trying to understand Spring proxy mechanism and I have problem with one thing.
I have Interface:
public interface MyInterface{
void myMethod();
}
and implementing class:
#Component
public class MyBean implements MyInterface{
#Override
public void myMethod(){
//do something
}
}
Now I create Aspect, for example:
#Aspect
#Component
public class LogAspect {
#Before("execution(public * *(..))")
public void logBefore() {
System.out.println("Before aspect");
}
}
And I have simple starter class:
#Configuration
#ComponentScan
#EnableAspectJAutoProxy
public class SpringAopApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
SpringAopApplication.class);
MyBean bean = ctx.getBean(MyBean.class);
// MyInterface bean = ctx.getBean(MyInterface.class); //works
bean.myMethod();
ctx.close();
}
}
According to the Spring docs we can read:
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
But I got an error No qualifying bean of type [MyBean] is defined. It works only when I enable CGLib proxying by #EnableAspectJAutoProxy(proxyTargetClass = true).
Can someone explain what I am missing here? Why MyBean is not discovered when using AOP? ctx.getBean(MyInterface.class) works, but I can't imagine the situation with many implementations of such interface.
The target object to be proxied (MyBean) implements at least one interface (MyInterface), so a JDK proxy is used.
This proxy implements MyInterface, but is NOT an instance of MyBean.
Thats why
MyInterface bean = ctx.getBean(MyInterface.class);
works and
MyBean bean = ctx.getBean(MyBean.class);
not.
CGLib proxies are created by subclassing the target object, so the bean created is a subclass of MyBean and implements MyInterface.
In this case also
MyBean bean = ctx.getBean(MyBean.class);
works.
...but I can't imagine the situation with many implementations of such interface.
The only reason for MyInterface could be, to allow spring to create a JDK proxy, so there is no need to have many implementations.
Because if you check up your bean class you'll find com.sun.proxy.$Proxy21 (or something similar) instead, which wraps your method. They are incompatible types even they have the same interface.
For example:
public interface AnInterface {
void func();
}
public class Bb implements AnInterface{
#Override
public void func() {
System.out.println("bb");
}
}
public class Cc implements AnInterface{
#Override
public void func() {
System.out.println("cc");
}
}
So when you call
public static void main(String[] args) {
Bb b = new Bb();
Cc c=b; // Error
AnInterface c=b; // Ok
}

Spring can you autowire inside an abstract class?

Spring is failing to autowire my object? Is it possible to autowire an object within an abstract class. Assume all schemas are supplied in application-context.xml
Question: What annotation should be on the base and extending classes (if any) #Service #Component?
Example
abstract class SuperMan {
#Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Extending class
public class SuperGirl extends SuperMan {
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
I have that kind of spring setup working
an abstract class with an autowired field
public abstract class AbstractJobRoute extends RouteBuilder {
#Autowired
private GlobalSettingsService settingsService;
and several children defined with #Component annotation.
Normally, Spring should do the autowiring, as long as your abstract class is in the base-package provided for component scan.
See this and this for further reference.
#Service and #Component are both stereotypes that creates beans of the annotated type inside the Spring container. As Spring Docs state,
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
What if you need any database operation in SuperGirl you would inject it again into SuperGirl.
I think the main idea is using the same object reference in different classes.
So what about this:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
#Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
#Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
In my opinion, inject once run everywhere :)
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring autowire dependency defined in an abstract class
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Dependency Injection into your Singleton

I have a singleton that has a spring injected Dao (simplified below):
public class MyService<T> implements Service<T> {
private final Map<String, T> objects;
private static MyService instance;
MyDao myDao;
public void set MyDao(MyDao myDao) {
this. myDao = myDao;
}
private MyService() {
this.objects = Collections.synchronizedMap(new HashMap<String, T>());
// start a background thread that runs for ever
}
public static synchronized MyService getInstance() {
if(instance == null) {
instance = new MyService();
}
return instance;
}
public void doSomething() {
myDao.persist(objects);
}
}
My spring config will probably look like this:
<bean id="service" class="MyService" factory-method="getInstance"/>
But this will instantiate the MyService during startup.
Is there a programmatic way to do a dependency injection of MyDao into MyService, but not have spring manage the MyService?
Basically I want to be able to do this from my code:
MyService.getInstance().doSomething();
while having spring inject the MyDao for me.
Here is a solution, create a class with a static factory method:
public class MyService {
private static MyService instance;
private MyDao myDao;
public static MyService createInstance(final MyDao myDao) {
instance = new MyService(myDao);
return instance;
}
private MyService(final MyDao myDao) {
this.myDao = myDao;
}
public static synchronized MyService getInstance() {
return instance;
}
public void doSomething() {
// just do it!
myDao.justDoIt();
}
}
and use spring to initilize it:
<bean class="my.path.MyService" factory-method="createInstance" scope="singleton">
<constructor-arg ref="reference.to.myDao" />
</bean>
and now you should be able to do:
MyService.getInstance().doSomething();
without any problems.
If you want a singleton, why not just define that one class in the Spring configs, and it's automatically a singleton (by default).
To avoid initialising at start up, have you looked at Spring lazy initialisation ? Basically you need:
lazy-init="true"
in your bean definition.
As mentioned by others, you should let spring manage your singletons, but if you want to manage them yourself and just let spring inject dependencies, do this:
applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService);
I believe the FactoryBean interface is a good alternative for you. It's a very good choice when you need to execute some initialization logic. For example to start an in memory database or some background processes in separate threads.
You can read more about it in the reference documentation.
An example that demonstrates how I instantiate a database and return a datasource everytime someone wants a bean from the FactoryBean implementation.
#PostConstruct
void init() {
embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath)
.addScript(dataPath).setType(embeddedDatabaseType).build();
}
public DataSource getObject() throws Exception {
return embeddedDatabase;
}
This enables loose coupling between the factory logic and the returned object. It's heavily used by the Spring framework internally.
If you want it to be initialized the first time you use it, then set lazy-initialization to true.
Another alternative if you want your code to interact with the Spring container is to create a factory that implements the ApplicationContextAware interface. Then you can do something like this:
myDao = context.getBean(MyDao.class);

Resources