Spring - passing a custom instance to a constructor - java

I'm trying to implement a command-query design pattern into
a MVC spring based application.
I have, for example, some decorated commands using decorator pattern
like bellow:
ICommandHandler handler =
new DeadlockRetryCommandHandlerDecorator<MoveCustomerCommand>(
new TransactionCommandHandlerDecorator<MoveCustomerCommand>(
new MoveCustomerCommandHandler(
new EntityFrameworkUnitOfWork(connectionString),
// Inject other dependencies for the handler here
)
)
);
How can I inject such a handler into a controller constructor? Where should
I instantiate this handler? A place where this can be instantiated can be
the controller constructor, but this isn't the best solution. Any other ideeas?
Thanks

If you're using PropertyPlaceholderConfigurer (old) or PropertySourcesPlaceholderConfigurer (new), and your connection string is in a .properties file or environment variable you can do the following for the connection string. You can also autowire objects into a configuration class and annotate a method with #Bean to do what the Spring context xml does. With this approach you can create your beans as you wish and they're available to autowire just like you defined them in xml.
#Configuration
public class MyAppConfig {
#Autowired private MyType somethingToAutowire;
#Bean
public ICommandHandler iCommandHandler(#Value("${datasource.connectionString}")
final String connectionString) {
return new DeadlockRetryCommandHandlerDecorator<MoveCustomerCommand>();
// You obviously have access to anything autowired in your configuration
// class. Then you can #Autowire a ICommandHandler type into one of your
// beans and this method will be called to create the ICommandHandler (depending on bean scope)
}
}

Related

Getting Spring beans by method invocation vs new operator

I am confused about this little topic. Somewhere I read that if a class is annotated with #Component, it is spring managed bean and whenever it is required, spring will provide it. I am confusing it with scope of a bean. Let me explain:
Let's say a class
#Component
public class Example{ }
If I instantiate this class in other class using new Example(), would container always provide me the same Example object all the time? Or would it return me new object every time?
Here comes the confusing part:
If in the same class I have two beans like this:
#Component
public class Example {
#Bean DataSource sqlDataSource() {
// some logic
}
#Bean #Scope("prototype") SomeObject getSomeObject() {
return new SomeObject(sqlDataSource()); //**
}
}
What will happen in this case? sqlDataSource() method invocation would return the same object again and again every time SomeObject bean is requested, or new instance of DataSource will be returned every time SomeObject is requested?
#Bean is a method-level annotation that indicates Spring to create a bean when that method is invoked. It means to have the same functionality thatn tag in XML config.
This annotation must be used inside of a #Configuration annotated class, otherwise if you invoke the method from another method it will be a normal java new operation, not spring's. See this post --> #Bean inside class with #Configuration and witout it
Bearing this in mind new SomeObject(sqlDataSource()); would be equal to new SomeObject(new SqlDataSource());
if you annotate Example with #Configuration what will happen is that you'll get always a new SomeObject instance with the same sqlDataSource object, this means that Spring will take care of creating ONLY ONE sqlDataSource because it is singleton.
#Bean DataSource sqlDataSource() {
// some logic
}
This defines a singleton instance of DataSource. So everytime you request an instance of SomeObject a new SomeObject will be created (while it is defined in the prototype scope) but all of them will share the same DataSource object (since it's a singleton bean).

Spring DI - Non-managed-object custom resolution

I have the following bean / constructor definitions:
#Configuration
class Configuration {
#Bean
public List<Something> getSomethings(MyFancyStuff stuff, #Autowired Bar bar) {
//...
}
}
#Component
class SomeOtherThing {
public SomeOtherThing(MyFancyStuff stuff, #Autowired Bar bar) {
//...
}
}
Is it possible to extends dependency resolution to provide a custom resolver when a specific class or annotation is found for a given parameter? I looked at PropertyPlaceholderConfigurer and InstantiationAwareBeanPostProcessor but nothing seemed to help me write my own value provider.
As a context: I implemented a custom scope which creates many instances of a given bean for each configuration object it has. I want to pass this configuration object to the bean-creation-process of said scope without adding it to the application context. I don't want to add it to the application context because it is an object which no other object should be able to obtain through dependency injection. I need to extend the DI-process of spring because I want to support field injection, constructor injection and bean factory-methods like the shown getSomethings
note: this is not about automatic value conversion of SpringMVC request parameters.
You can use #Conditional Annotation
#Bean(name="dataSource")
#Conditional(value=DevCondition.class)
public Util getSource1() {
return new DevUtil();
}
#Bean(name="dataSource")
#Conditional(ProdCondition.class)
public Util getSource2() {
return new ProdUtil();
}
you can also create bean based on property value using #Profile

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

Using class.forname but want to autowire members of the target class

I have this requirement,
My framework is in a way that it reads the class name from the configuration file as a string and I would like to use methods inside that class.
Obvious solution is to use reflection,
I have used reflection and able to call methods I wanted, but the problem is the variables inside the target class are not autowired. I understand I am not letting spring to autowire the fields by using reflection (Spring with class.forname()).
Is there a way for me to autowire the class variables instead of creating new instance? Or Am I in a deadlock situation?
Option 1: If you have access to the current Spring ApplicationContext, you could do this as follows:
String className = <load class name from configuration>
Class<?> clazz = Class.forName(className);
ApplicationContext applicationContext = <obtain Spring ApplicationContext>
applicationContext.getBean(clazz);
This of course means that the class whose instance you wish to load is a Spring managed bean. Here is a concrete example:
package org.example.beans;
#Component
class Foo { ... }
#Component
class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
#Override
public void setApplicationContext(final ApplicationContext context) throws BeansException
CONTEXT = context;
}
public static <T> T getBean(String className) {
return CONTEXT.getBean(Class.forName(className));
}
}
Option 2: You could manually create an instance of the required class and then ask Spring to populate its dependencies.
This again requires access to the ApplicationContext. For example:
T object = Class.forName(className).newInstance();
applicationContext..getAutowireCapableBeanFactory().autowireBean(object);
It's possible. Have a look at how Spring's JUnit test integration does it. That's in the spring-test module.
The runner is SpringJUnit4ClassRunner, but the actual injection code is in DependencyInjectionTestExecutionListener.injectDependencies. It uses a Spring context that implements AutowriteCapableBeanFactory.
The code to do this looks like below. Note that this assumes that you have used annotations to indicate which fields need to be autowired.
Object bean = ...;
AutowireCapableBeanFactory beanFactory = ...;
beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
beanFactory.initializeBean(bean, "beanName");

Create servlet context without autowiring in spring

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()

Categories

Resources