2

I am wondering if it is possible to accomplish the following using EJB3.

I have the following interface:

interface DateParser {
    Date parseDate(String input);
    String getType();
}

Then I have several implementations of said interface that handle different formats based on the information given in the getType method. When my bean starts up it creates a Set of implementations of DateParser and when it needs to parse a date, it iterates over the set to see which one matches. If one matches it uses that one to parse the date. If none match, then it applies a default strategy. I would like to get away from instantiating these delegates because every time I add a new strategy it requires a code change in the bean making it a huge mess.

I would much prefer to have the container inject all of the implementations it finds at deployment. Is there a reasonable way to accomplish this?

Thanks

babernathy
  • 803
  • 2
  • 8
  • 23
  • 1
    If you are adding a new strategy, presumably THAT itself is a code change (a new strategy class)? It sounds like you need the strategy classes register themselves with a factory and your main processor can simply ask the factory to provide the matching implementation. – Paul Jowett Aug 16 '12 at 02:36
  • Very true. I could simply register them with a factory. The goal is to then have them automatically register them. – babernathy Aug 16 '12 at 03:21

3 Answers3

1

Implementation of this interface should be regular classes, not beans. EJB are meant to be business services. Parsing date is IMHO a responsabiltiy that is too fine-grained for a bean.

I would much prefer to have the container inject all of the implementations it finds at deployment.

I don't think there is standard way to do that. I see only two options to dynamically fill the set with the instances:

  1. Use an external configuration files with list of class names. Reach each class name and instantiate one instance reflectively (Class.forName, Class.newInstance). Then add it to the set.

  2. Iterate over all classes in the class path, identifiy those that are implementation of DateParser. Then instantiate it reflectively, and add it to the set. Note that iterating over loadable classes is kind of tricky, see this answer.

it requires a code change in the bean making it a huge mess.

That should require a code change in a class, but not the bean itself. The bean should delegate the creation of the set, the identification of the parser, etc. to another class, IMHO.

Community
  • 1
  • 1
ewernli
  • 38,045
  • 5
  • 92
  • 123
  • I agree with your answer. My final solution was to implement a factory class that returned parsers based on a match. That isolated the changes involved in adding a new parser type to the factory class. – babernathy Aug 23 '12 at 19:19
0

Yes you can, see this sample;

    @EJB(beanName = "yourSessionEJB")
    DateParser dateParser;

you can change other session bean name into beanName attribute. But one local interface used one session bean is recommended and not confused.

Sai Ye Yan Naing Aye
  • 6,622
  • 12
  • 47
  • 65
  • Not quite what I was looking for. In a strategy pattern you seek to have multiple implementations of the same interface then delegate to the proper one based on what you are trying to accomplish. Your example only injects a single interface. – babernathy Aug 16 '12 at 13:24
0

If you want to get all the implementations of some interface, you can use @Any annotation with Instance interface.

Take a look at this: https://goo.gl/Kbn0bP

bruno.zambiazi
  • 1,422
  • 14
  • 19