Creating non-bean instances with Spring - spring

I'm sure this has been asked a hundred times before but I can't seem to find the question so feel free to refer me to other stackoverflow answers.
What do most Spring users do for objects that are non-singleton beans that require injection? For example, I have classes like Customer where I want to instantiate a new one each time. Lets say it is an entity and I want to inject listeners to iterate through in #PreRemove or somewhere else. The usual solution is to use #Configurable but that almost seems a workaround and I was wonder if there was a more canonical way to handle these.
The only thing I can think of is to create a factory newCustomer instance method in my CustomerRepository class which IS a managed bean. Then instead of injecting listeners into Customer (the most natural place) I inject them into the CustomerRepository and specify them as an explicit constructor argument to Customer ala new Customer( injectedListeners ).
Do people tend to just use Configurable or is there a better way to inject non-singleton instances? Or do most users create a factory method as above? The entity example is just an example, I have other objects that are non-singleton, are typically new'd but require injection.
Would this be handled differently in something like Guice? How would you do it just using JSR-330 features?

You can make beans non-singletons if you like. Depends on whether you are ok with the XML:
<bean id="beanA" class="misc.BeanClass" scope="prototype">
<property ... />
</bean>
Which will give you a new instance every time. Each instance will be initialized with injected values.
You can use this annotation too:
#Scope("prototype")

Related

Single spring bean with two different ids in same xml(application context)

If we create a new another bean with different id in the same xml for the same class, will spring produce another singleton bean(in same ApplicationContext)?
As per my understanding there should be only one instance of the bean in single ApplicationContext.
Below example-
<bean id="bean1" class="com.myCompany.myPackage.MyClass" scope="singleton" />
<bean id="bean2" class="com.myCompany.myPackage.MyClass" scope="singleton" />
To keep it short: No, the singleton only says that you'll have: "one shared instance, which will be returned by all calls to getBean with the given id" (that's what the documentation states).
So, you can do any number of calls to application context and obtain "bean1" and you'll always get the same instance, but if you call by "bean2" id, you'll get another instance.
The "singleton" says that you'll have only one object. Now in a non-Spring application, you'll have it usually per JVM. But in spring application, let the framework manage this. So usually you'll want to define only one class like "MyClass" with a scope singleton.
When dependency management container (Spring in this case) manages singletons, it has a lot of advantages over the 'regular' singleton. Just to name a few:
Much easier to test
You always know when the object is created and when it becomes subject to garbage collector
No static code (the Spring driven singleton is just a regular bean with no statics)
But in general it's not directly related to your question.
I did have this same question just in a different context of Spring's singleton vs. Java's singleton and I found this answer provided by 'Dexter' in this link more subtle and easy to understand.
Also, this blog here provides a perfect example for the same which is backed by the official spring documentation for better-detailed understanding.
Hope these pointers help. Thanks.

Spring web app controller field scope

I am experiencing some conceptional difficulty with the scope of some beans referenced in controllers. I have checked a lot of related questions in file and still not sure. Could someone please help me clarify it?
I am numbering the questions or statements as follows to make helper easier to address my problems.
Per my understanding from the the Spring doc, in spring web application,
1) for any controller, annotated with a #Controller, if there is a private field bean, with default bean scope, this field bean will be accessed as the singleton thus susceptible to thread issue;
2) If the field bean is marked as scope=""prototype, this field bean, within this controller, will still behave like a singleton, thus being not-thread safe.
3) To make such a field bean thread safe, we have to make the bean scoped with request or session right?
The following is a simplified example related to this question:
#Controller public Class ControllerA
#Autowired private DefinedBean db;
#RequestMapping("/testPath") public ModelAndView getPathPage(){
this.db.setTitle("abc");
this.db.readReportWithTitle();
....
return new ModelAndView();
}
So in this example,
4) if the DefinedBean is defined through xml configuration with or without explicit scope of prototype, this DefinedBean will have synchronization issue, right?
5) To ensure this DefinedBean to be thread safe, we have to define it explicitly with request or Session.
On the other hand,
6) if we mark the controller itself with a scope of prototype explicitly, will it get rid of the non-thread safe issue with the DefinedBean field? My thought is no, this won't.
7) To make the field thread safe, if we are going to control at the controller level, we need to mark the controller with Scope="Request" as well, right?
Your comments are welcome and appreciated. If you can comment with "Correct" Or "Incorrect" or elaborate further to those numbered (1~7) statements, Myself and possible those who come later will appreciate more.
I think you want to leave the controller be a singleton.
Here is the spring documentation that explains how to bind beans having different scopes.
This is how you would want to define the wired bean:
<bean id="db" class="DefinedBean" scope="request">
<aop:scoped-proxy/>
</bean>
I have looked up to see how the same can be done with annotations only and I have found this.
Basically, you annotate DefinedBean with :
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)

Custom annotation like #Value

I need to create a means to add a custom annotation like
#Value("${my.property}")
However, in my case I need to get the value from a database rather then a properties file.
Basically I would like to create a bean on container startup that reads in property name value pairs from a database and can then inject these into fields belonging to other beans.
Approach #1:
One way is to create an Aspect, with a point-cut expression that matches any method having this annotation.
Your aspect will then:
Read the property value in the annotation
Look up the required value an inject it into the class.
AOP Kickstart
Here's a guide to getting started with AOP in Spring
http://www.tutorialspoint.com/spring/aop_with_spring.htm
Joinpoint matching
Here's a reference that describes how to create a join-point that matches on annotations: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
Approach #2:
Another way is to use a BeanFactoryPostProcessor - this is essentially how a PropertyPlaceholderConfigurer works.
It will look at your bean definitions, and fetch the underlying class.
It will then check for the annotation in the class, using reflection.
It will update the bean definition to include injecting the property as per the value in the annotation.
. . actually I think approach #2 sounds more like what you want - all of the processing happens on "start-up". . . (In actual fact your modifying the bean recipes even before startup). . whereas if you used AOP, you'd be intercepting method invocations, which might be too late for you?
Namespace Handler
If you wanted you could even create your own Spring namespace handler to turn on your post processor in a terse way. Eg:
<myApp:injectFromDb />
as an alternative to:
<bean class="MyDatabaseLookupProcessorImpl etc, etc. />
Update: Approach #3
As of Spring 3.1 there's also the PropertySourcesPlaceholderConfigurer, that will provide most of the plumbing for you, so you can achieve this with less code.
Alternatively you should be able to configure kind of properties repository bean and then use it in SpEL directly in #Value annotation.
Let's say you'd have bean called propertiesRepository in your context that implements following interface:
interface PropertiesRepository {
String getProperty(String propertyName);
}
then on bean where you want to inject values you can use following expression
#Value("#{propertiesRepository.getProperty('my.property')}")
String myProperty;
You can use #Value annotation by injecting database configuration in application environment itself.
I know this is an old question but I didn't find an exact solution. So documenting it here.
I have already answered the same on different forum.
Please refer to this answer for exact solution to your problem.

Constructors in Bean

I have one small issue with creating a new bean. Basically as per request, I get some parameters, which needs to be passed to a bean. Below I am instantiating ControllerService for each request. Rather I would like it to be a bean with scope=protype. So that I get a fresh object for every request.
But then how do i set the 2 properties (kpiName, kpiInput) that I am sending via constructors in the bean??
#Autowired
#Qualifier("serviceManager")
Cleanser serviceManager;
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody
String getKPIResult(#RequestParam("kpiName") String kpiName,
#RequestParam("kpiInput") String kpiInput) {
return serviceManager.checkAndExecute(new ControllerService(kpiName, kpiInput));
}
In situations like this where you're going against the grain of Spring, I'd suggest that perhaps you're doing something in a way that's not considered best practice. Without more context it's hard to see though.
Spring Social uses a request scope bean to embody a repository for a specific user. I've now idea why as it's a horribly inefficient way of doing things, and much less understandable IMHO.
<bean id="connectionRepository" factory-method="createConnectionRepository"
factory-bean="usersConnectionRepository" scope="request">
<constructor-arg
value="#{T(org.springframework.security.core.context.SecurityContextHolder).getContext().getAuthentication().getPrincipal()}" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
You can see here the use of factory-bean and factory-method to declare a class/method to call when wanting an instance of your class. The constructor argument is passed using SpEL. I'm not quite sure how you'd achieve this with Spring MVC responding to web requests, but I'm fairly sure you could use Spring Integration to pass a message and use SpEL to grab headers/payload form that message to pass to the constructor.
Again though, I'd really question your design pattern here - a more usual SOA idiom is to create services on startup, and have them as stateless as possible from there-on in, rather than create an instance with specific state for each request. Best of luck!
Don't. The Controller as it's intended in Spring MVC is largely derived from the old Java servlet, which should be stateless by specification.
In fact, Controller-objects are hard-cached inside the handler mapping framework and not fetched from the bean context on each request. Setting scope to "prototype" would, effectively, do nothing as the handler (controller) is really only gotten once.

Spring config and runtime separation

When using Spring it is rather cumbersome to incorporate runtime data in bean construction. While there are techniques to circumvent this separation, I have a feeling that it was put in place for a reason. My question is whether this is a known paradigm, and if there is any litterature discussing it. Personally I find that it has both advantages and drawbacks, depending on the dynamicity of the app.
You have at least five well known methods to pass runtime data to beans configuration:
Use ApplicationContextInitializer to add PropertySources to the Enviroment.
Use SPEL to inject dependencies.
Use FactoryBeans.
Use the factory-bean and factory-method attributes.
If you write the class that need the runtime data, you only need to inject the
collaborator that provide it.
For example
<bean id="requestAttributeReader" class="example.RequestAttributeReader" />
<bean id="requestInjectedBean" class="example.RequestInjectedBean" scope="request">
<property name="a" value="#{requestAttributeReader.a}" />
</bean>
Class RequestAttributeReader {
public String getA() {
return RequestContextHolder.getAttributes().getAttribute("a");
}
}
EDIT
The bean description files of an IoC container lets you to configure implementors on application beans. This is normally a static definition of the implementation classes that you want to use for a concrete configuration, so xml it's good for it.
If you need to choose an implementor based on runtime then you need to write code to choose them and then inform the container.
for example, using PropertySources and PropertyPlaceholderConfigurer:
String service = "example.NormalService";
if (BOSS_USERNAME.equals(System.getProperty("user.name")))
service = "example.BossService";
ctx.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("service", service));
<bean id="service" class="${service}" />
The same could be done with a ServiceFactoryBean, a external ServiceFactory, SPEL and so on...
Maybe, you are interested on replacing implementations at runtime, ie changing the Service implementation in all beans that depends on when the container is already refreshed. (without destroy and refresh).
As far as I know, the framework don't provides a clear way to do it.
Sounds like you should look at spring binding, eg:
public String create(#Valid Market market, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
So this will take request params that match the fields in the Market object and set them in that object. It will also validated the params/object since there is the #Valid annotation.
This binding can be customised with PropertyEditors or Converters.
If the market object is annotated #Configurable, it can use #Autowired and #Value annotations to configure the bean when spring creates it.

Resources