Define and inject a map in EJB 3.1 or CDI - spring

After several years developing in Spring, I switched to EJB and I am not happy that I have no solution for this use-case. Let's say it is the strategy pattern implemented by a map. In Spring, it could look like this.
<bean id="myBean" class="MyBeanImpl">
<property name="handlers">
<map>
<entry key="foo" value-ref="fooHandler"/>
<entry key="bar" value-ref="barHandler"/>
</map>
</property>
</bean>
In EJB/CDI, I have this.
#Stateless
public class MyBeanImpl implements MyBean {
private Map<String, Class<? extends Handler>> handlers = new HashMap<>();
#PostConstruct
public void init() {
handlers.put("foo", FooHandlerImpl.class);
handlers.put("bar", BarHandlerImpl.class);
}
//jndi lookup handlerClass.getSimpleName()
}
Mind that jndi lookup works with implementations, not interfaces. Isn't there any better solution? And no, I do not want to have separate fields (foo, bar), inject them and create the map afterwards (It can be huge list and changed often). Ideally, in case of any configuration change, I would not touch the MyBeanImpl class at all.

The more CDI like way would look something like:
#Qualifier
#Target({ TYPE, METHOD, PARAMETER, FIELD })
#Retention(RUNTIME)
#Documented
public #interface Handles {
String value();
}
public class HandlerLiteral extends AnnotationLiteral<Handles> implements Handles{
private final String value;
public HandlerLiteral(String value) {
this.value = value;
}
#Override
public String value() {
return value;
}
}
You would then annotate each of your Handler implementations with #Handles("someName"), e.g. the class name as you're using it here. The use of a qualifier here is more in line with how CDI works, and we use the internal Instance object to resolve appropriate beans. Then in your service code (or wherever) you would simply do:
#Inject #Any
private Instance<HandlerService> handlerInstance;
...
handlerInstance.select(new HandlerLiteral("whateverName")).get().handle(context);
If you're really constrained to using a map, this wouldn't work for you. But this should allow for more dynamic registration and essentially looks at every handler in your context.

Try this:
#Inject #Any
private Instance<Handler> handlers;
private Map<String, Handler> handlerMap = new HashMap<>();
#PostConstruct
private void init() {
for (Handler handler : handlers) {
handlerMap.put(handler.getName(), handler);
}
}
assuming your Handler interface has some sort of getName() method.

Related

Autowired not working as expected

I'm using Spring Roo and want to access a bean within of Controller class which has following configuration in applicationContext.xml:
<bean class="com.reservation.jobs.Configuration" id="jobsConfiguration" autowire="byType">
<property name="skipWeeks" value="4" />
</bean>
The configuration class itself is:
package com.reservation.jobs;
public class Configuration {
private int skipWeeks;
public void setSkipWeeks(int value) {
System.out.println("SkipWeeks set auf: " + value);
this.skipWeeks = value;
}
public int getSkipWeeks() {
return this.skipWeeks;
}
}
In my Controller I thought that a simple Autowired annotation should do the job
public class SomeController extends Controller {
#Autowired
private com.reservation.jobs.Configuration config;
}
During startup Spring prints the message within the setSkipWeeks method. Unfortunately whenever I call config.getSkipWeeks() within the controller it returns 0.
Have I to use the getBean method of the ApplicationContext instance or is there some better way?
autowire="byType" is redundant. It indicates that fields of the Configuration class should be autowired, and you have just one primitive. So remove that attribute.
Apart from that, config.getSkipWeeks() must return 4 unless:
you are using a different instance (made by you with new)
you have called the setter somewhere with a value of 0

Spring beans with runtime initialization parameters

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.

How do I dynamically create dependency implementations as they are referenced in Spring?

The situation here is that I have an interface that has dynamic implementations. These implementations need to be instantiated at runtime and used by injecting the interface:
public interface Configuration {
void doStuff();
}
public interface ExampleConfiguration extends Configuration {
void doStuff();
}
ExampleConfiguration has an implementation generated dynamically. I.e, there is no ExampleConfigurationImpl class. This is proving difficult to integrate into Spring because I want to have these generated implementations injected automatically:
#Autowired
private ExampleConfiguration config;
I went down the road of adding a BeanPostProcessor but it looks like unresolved dependencies don't go through there (as I would expect).
Essentially, is there a way to contribute a factory that will be called (with contextual information such as a DependencyDescriptor instance) in an attempt to resolve a missing dependency? There will be multiple interfaces extending the Configuration interface.
Spring version is 3.0.3.
Have you tried a FactoryBean?
public class ExampleConfigurationFactoryBean implements FactoryBean<ExampleConfiguration> {
#Override
public ExampleConfiguration getObject() throws Exception {
return //...magic here
}
#Override
public Class<?> getObjectType() {
return ExampleConfiguration.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
I don't know how you actually create these dynamic beans (I suspect some dynamic proxy being involved), but insert your logic in magic here placeholder. Should work. You use the FactoryBean as if it had a target type in your XML:
<bean id="exampleConfigurationFactoryBean" class="ExampleConfigurationFactoryBean"/>
<bean id="someBean">
<!-- exampleConfiguration is of ExampleConfiguration type -->
<property name="exampleConfiguration" ref="exampleConfigurationFactoryBean"/>
</bean>
Spring will call getObject() when requested.
I assume you've got some way to actually manufacture the instances? Well, all you need to do is to make that factory into a bean itself and add the right annotations:
#org.springframework.context.annotation.Configuration
public class ConfigBean {
#org.springframework.context.annotation.Bean
public ExampleConfiguration getObject() throws Exception {
return //...magic here
}
}
You use the usual Spring techniques for hooking to any configuration you need. (I assume you're using <context:component-scan> and <context:annotation-config>…)

Get AOP proxy from the object itself

Is possible to get the proxy of a given object in Spring? I need to call a function of a subclass. But, obviously, when I do a direct call, the aspects aren't applied. Here's an example:
public class Parent {
public doSomething() {
Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
public class Child extends Parent {
#Secured("president")
public void sayHello() {
System.out.println("Hello Mr. President");
}
}
I've found a way of achieving this. It works, but I think is not very elegant:
public class Parent implements BeanNameAware {
#Autowired private ApplicationContext applicationContext;
private String beanName; // Getter
public doSomething() {
Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
This hack is extremely awkward, please consider refactoring your code or using AspectJ weaving. You may feel warned, here is the solution
AopContext.currentProxy()
JavaDoc. I blogged about it here and here.
AopContext.currentProxy() as suggested by Tomasz will work. A more generic solution, that will work outside of the proxied class is to cast the object to org.springframework.aop.framework.Advised and get .getTargetSource().getTarget()
The former (getting the real object from the proxied object) is something that you should not really need. On the other hand getting the target proxy might be useful in some utility class that inspects existing beans in order to add some feature.
You can use a bean post-processor to set a reference to the proxy on the target bean. It moves the Spring-specifics from your beans to a single class.
Post-Processor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class SelfReferencingBeanPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof SelfReferencingBean) {
((SelfReferencingBean) bean).setProxy(bean);
}
return bean;
}
}
Context
Register the post-processor in applicationContext.xml.
<bean id="srbpp" class="SelfReferencingBeanPostProcessor"/>
Beans
Each bean must implement SelfReferencingBean to tell the post-processor that it needs a reference to the proxy.
public interface SelfReferencingBean {
void setProxy(Object proxy) ;
}
Now implement setProxy in each bean that needs to call itself through its proxy.
public class MyBean implements SelfReferencingBean {
MyBean proxy;
#Override
public void setProxy(Object proxy) {
this.proxy = (MyBean) proxy;
}
}
You could put this last bit of code into a bean base class if you don't mind casting proxy to bean's type when calling methods directly on it. Since you're going through Method.invoke you wouldn't even need the cast.
With a little work I bet this could be converted to an annotation processor a la #Autowired. Come to think of it, I don't recall if I even tried adding a self-reference using #Autowired itself.
public class MyBean implements SelfReferencingBean {
#Autowired MyBean proxy;
}

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