Spring Instantiation using a none-static factory method - spring

I have got a situation where I would like to create bean2 in Spring config:
beans.xml:
<bean id="bean1" class="...">
<property name="..." ref="..." />
</bean>
bean2 = bean1.foo()
Would appreciate any help,
Thanks,
Behzad

You can use instance factory method. See corresponding chapter in Spring documentation.
<bean id="bean2" factory-bean="bean1" factory-method="foo"/>

If you are using annotations you can use:
#Configuration
public class AppConfig {
#Bean
#Lazy
public Bean1 getBean1(){
return Bean1.getInstance();
}
#Bean
public Bean2 getBean2() {
return this.getBean1().newBean2(); //in your example is this.getBean1().foo();
}
}

Related

Camel #Header annotation not working when using spring ProxyFactory

When I use the camel #Header annotation in an interface, and call the bean (that implements it) directly, the Header value is filled. But when I proxy it with the spring ProxyFactoryBean then the #Header annotated parameter is empty. Probably I'm doing something wrong or am missing part of the configuration.
public interface Foo {
public void execute(#Header("FooHeader") String headerValue);
}
public class FooImpl implements Foo {
public void execute(String headerValue) {
System.out.println(headerValue);
}
}
public class FooInterceptor implements org.aopalliance.intercept.MethodInterceptor {
public Object invoke(final MethodInvocation invocation) throws Throwable {
return invocation.proceed();
}
}
spring context:
<bean id="foo" class="FooImpl"/>
<bean id="fooInterceptor" class="FooInterceptor"/>
<bean id="fooProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="foo"/>
<property name="interfaces">
<list>
<value>Foo</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>fooInterceptor</value>
</list>
</property>
</bean>
The camel route DSL:
from("foo-queue").to("bean:foo?method=execute");
prints the value of the header, but the route:
from("foo-queue").to("bean:fooProxy?method=execute");
prints null. Seems that in my setup, camel does not "see" the header annotation that's on the interface, that the proxy implements.
So, how can I make camel see the annotation and inject the value of the header as an argument to the method?
ProxyFactoryBean is a spring and not Camel, and as such it does not know about those Camel annotations.
Instead see here how to use Camel Proxy in Spring XML files: http://camel.apache.org/using-camelproxy.html

Injecting spring bean to an abstract class

I'm trying to inject (autowire) a spring bean to an abstract class but it doesn't seem to work.
public abstract class BaseEntity {
#Autowired(required = true)
protected SecurityProvider securityService;
public BaseEntity() {
}
}
And the injected class:
#Component
public class SecurityService extends SecurityProviderImpl implements SecurityProvider {
#Autowired
public SecurityService(ICipherDescriptor cipherDescriptor) {
super(cipherDescriptor);
}
}
The SecurityService gets initialized just fine (I can see it while debugging) but the class that inherit from BaseEntity cannot use the injected SecurityService since it is null (doesn't get injected for some reason).
I tried doing it via XML as well, defining the BaseEntity as abstract:
<bean id="baseEntity" abstract="true" class="com.bs.dal.domain.BaseEntity">
<property name="securityService" ref="securityService"/>
</bean>
<bean id="securityService" class="com.bs.dal.secure.SecurityService">
<constructor-arg ref="cipherDescriptor" />
</bean>
but still with no success.
Where am I going wrong?
I think I know what's wrong here. I'm trying to inject a spring bean to an entity - which is impossible (unless you use aspectJ weaving) since the entities are not instantiated/managed by Spring. Make sense, isn't it?
If your BaseEntity is also instantiated by spring, you just need to add a parent attribute to the bean definition to link it to your BaseEntity definition like so:
<bean id="baseEntity" abstract="true" class="com.bs.dal.domain.BaseEntity">
<property name="securityService" ref="securityService"/>
</bean>
<bean id="derivedEntity" parent="baseEntity" class="com.bs.dal.domain.DerivedEntity"/>
<bean id="securityService" class="com.bs.dal.secure.SecurityService">
<constructor-arg ref="cipherDescriptor" />
</bean>
In short, the two key parts to such a definition are the abstract attribute on the parent class and the parent attribute on the subclass.

Getting an EhCache instance with Spring... intelligently

I need to get a specific EhCache instance by name and I'd prefer to autowire if possible. Given the following automatically configured controller, how can I autowire in the cache instance I'm looking for?
#Controller
public class MyUniqueService {
...
}
<beans ...>
<ctx:component-scan base-package="my.controllers"/>
<mvc:annotation-driven />
</beans>
How do I configure EhCache in my application context? I don't see any log messages from EhCache about it loading the ehcache.xml file in my /WEB-INF/ directory. How do I make it load it?
How can I integrate EhCache with my Spring application to have it load the ehcache.xml file from my /WEB-INF/ directory and autowire a cache by a given name into my MyUniqueService controller?
First you need to create a Ehcache CacheManager singleton in you app context like this:
<bean id="myEhCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:my-ehcache.xml"/>
</bean>
Here configLocation is set to load from classpath or use value="/WEB-INF/my-ehcache.xml".
In your controller simply inject the CacheManager instance:
#Controller
public class MyUniqueService {
#Resource(name="myEhCacheManager")
private CacheManager cacheManager;
...
}
Alternatively, if you'd like to go the "entirely autowired" route, do:
<bean class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/ehcache.xml"/>
</bean>
</property>
</bean>
Setup your class like so:
#Controller
public class MyUniqueService {
#Autowired
private org.springframework.cache.CacheManager cacheManager;
public org.springframework.cache.Cache getUniqueObjectCache() {
return cacheManager.getCache("uniqueObjectCache");
}
}
uniqueObjectCache corresponds to this cache instance in your ehcache.xml cache definition:
<cache name="uniqueObjectCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"
transactionalMode="off"/>
There isn't a way to inject an actual cache instance, but as shown above, you can inject a cache manager and use it to get the cache you're interested in.
Assuming you have cacheManager defined:
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:/ehcache.xml"/>
</bean>
You can get/inject specific cache like this:
#Value("#{cacheManager.getCache('myCacheName')}")
private Cache myCache;
See also examples how to use Spring EL inside the #Value() http://www.mkyong.com/spring3/spring-el-method-invocation-example/ if you are interested.
You can also use autowire if the context can find a bean with the correct class. Here is how I configured my xml
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>WEB-INF/ehcache.xml</value>
</property>
</bean>
<bean id="cache" class="net.sf.ehcache.Cache" factory-bean="cacheManager" factory-method="getCache">
<constructor-arg value="CacheNameHere" />
</bean>
And my java class
#Autowired
private net.sf.ehcache.Cache cache;
This setup works for me.
Indeed! Or if you want to use a java config class:
#Inject
private ResourceLoader resourceLoader;
#Bean
public CacheManager cacheManager() {
EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
try {
ehCacheCacheManager.setCacheManager(ehcacheCacheManager().getObject());
} catch (Exception e) {
throw new IllegalStateException("Failed to create an EhCacheManagerFactoryBean", e);
}
return ehCacheCacheManager;
}
#Bean
public FactoryBean<net.sf.ehcache.CacheManager> ehcacheCacheManager() {
EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
bean.setConfigLocation(resourceLoader.getResource("classpath:ehcache.xml"));
return bean;
}

Inject a file resource into Spring bean

What is a good way to inject some file resource into Spring bean ?
Now i autowire ServletContext and use like below. Is more elegant way to do that in Spring MVC ?
#Controller
public class SomeController {
#Autowired
private ServletContext servletContext;
#RequestMapping("/texts")
public ModelAndView texts() {
InputStream in = servletContext.getResourceAsStream("/WEB-INF/file.txt");
// ...
}
}
Something like this:
#Controller
public class SomeController {
private Resource resource;
public void setResource(Resource resource) {
this.resource = resource;
}
#RequestMapping("/texts")
public ModelAndView texts() {
InputStream in = resource.getInputStream();
// ...
in.close();
}
}
In your bean definition:
<bean id="..." class="x.y.SomeController">
<property name="resource" value="/WEB-INF/file.txt"/>
</bean>
This will create a ServletContextResource using the /WEB-INF/file.txt path, and inject that into your controller.
Note you can't use component-scanning to detect your controller using this technique, you need an explicit bean definition.
Or just use the #Value annotation.
For single file:
#Value("classpath:conf/about.xml")
private Resource about;
For multiple files:
#Value("classpath*:conf/about.*")
private Resource[] abouts;
What do you intend to use the resource for? In you example you don't do anything with it.
From it's name, however, it looks like you are trying to load internationalisation / localisation messages - for which you can you a MessageSource.
If you define some beans (possibly in a separate messages-context.xml) similar to this:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>WEB-INF/messages/messages</value>
</list>
</property>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en_GB" />
</bean>
Spring will load your resource bundle when you application starts. You can then autowire the MessageSource into your controller and use it to get localised messages:
#Controller
public class SomeController {
#Autowired
private MessageSource messageSource;
#RequestMapping("/texts")
public ModelAndView texts(Locale locale) {
String localisedMessage = messageSource.getMessage("my.message.key", new Object[]{}, locale)
/* do something with localised message here */
return new ModelAndView("texts");
}
}
NB. adding Locale as a parameter to your controller method will cause Spring to magically wire it in - that's all you need to do.
You can also then access the messages in your resource bundle in your JSPs using:
<spring:message code="my.message.key" />
Which is my preferred way to do it - just seems cleaner.

Does Spring framework makes possible to inject a collection in annotation-driven fashion?

Is it possible to do the same using annotation-driven injection:
<beans>
...
<bean id="interceptorsList" class="com.mytest.AnyAction">
<property name="interceptors">
<list>
<ref bean="validatorInteceptor"/>
<ref bean="profilingInterceptor"/>
</list>
</property>
</bean>
</beans>
Is it possible to do the same using annotation-driven injection?
Good question - I don't think so (assuming that by "annotation-driven injection" you're referring to annotations on AnyAction).
It's possible that the following might work, but I don't think Spring recognises the #Resources annotation:
#Resources({
#Resource(name="validatorInteceptor"),
#Resource(name="profilingInterceptor")
})
private List interceptors;
Give it a try anyway, you never know.
Other than, you can use #Configuration-style configuration instead of XML:
#Configuration
public class MyConfig {
private #Resource Interceptor profilingInterceptor;
private #Resource Interceptor validatorInteceptor;
#Bean
public AnyAction anyAction() {
AnyAction anyAction = new AnyAction();
anyAction.setInterceptors(Arrays.asList(
profilingInterceptor, validatorInteceptor
));
return anyAction;
}
}
Yes, Spring will happily inject all configured interceptors if you use this pattern:
#Autowired
public void setInterceptors(List<Interceptor> interceptors){
this.interceptors = interceptors;
}
private List<Interceptor> interceptors;
Note that you will probably have to configure default-autowire=byType on your context.xml. I don't know if there's an alternative to this in plain annotation configuration.

Resources