Pergunta

I got Object coming in a REST web service controller's web method which is locally initialized.

@RequestMapping(method = RequestMethod.POST,value = "/test",headers="Accept=*/*")
    public @ResponseBody ModelAndView computeDetails(@RequestBody RequestObj reqObj, ModelMap model) {

        System.out.println(reqObj.getcode());

        return new ModelAndView("responsedetails", "object", reqObj);
    }

This RequestObj object holds the key code to instantiate dependency using factory.

Different codes classes have been defined which implement BaseCode Interface.

How can I use factory method to instantiate particular code class based on code value coming in as BaseCode type in my service bean?

Any idea? Thanks in advance.

Foi útil?

Solução 3

I did it this way -

Make your factory as ServletContextAware in a way to get the currentContext. And define getInstance method as

WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

ctx.getBean(classNameToBeInstantiated);

Define your bean's inheritance in spring context so that Spring injects its dependencies.

Outras dicas

What I usually do in such cases is:

  1. inject the factory into the controller using Spring's bean
  2. create a method getBaseCode(String code) in the factory (please note: String here stands for code type, so use the actual code type if not String
  3. make getBaseCode returning the BaseCode interface while constructing the real implementation
  4. supposing you have an execute method in BaseCode, use the getBaseCode method into the controller to get the real collaborator and then call the execute method to perform the actual action


Ignoring the first point (which I think you can easily looking at any Spring tutorial) the factory will be something like

public class BaseCodeFactory {
  public BaseCode getBaseCode(String code) {
    if(code.equals("something")) return new ThisBaseCodeImpl();
    else //and so on
  }
}

while computeDetails becomes similar to:

@RequestMapping(method = RequestMethod.POST,value = "/test",headers="Accept=*/*")
public @ResponseBody ModelAndView computeDetails(@RequestBody RequestObj reqObj, ModelMap model) {
  //...
  factory.getBaseCode(reqObj.getcode()).execute();
  //...
}

As a side note, I will not go for names like the one I choose here, I suggest you to look for something more significative in your domain (BaseCode has no meaning for example), take this snippets just as a directive.

Base on OP comment. If you have ThisBaseCodeImpl which makes use of other Spring bean you can

  1. annotate it with @Configurable so, when you use new ThisBaseCodeImpl(/*args if you like*/) its bean are instantiated by Spring. I don't personally like this solution since, in my opinion, it pollutes the code with hidden Spring's bean. On the other hand is quite flexible, since it allows you to manage both runtime constructor arguments and Spring beans
  2. add ThisBaseCodeImpl to the Spring context and change the factory, so that a collaborator for ThisBaseCodeImpl is injected into it.

1st point example:

@Configurable
public class ThisBaseCodeImpl {
  @Resource
  private Bean bean;
}

2nd point example:

public class BaseCodeFactory {
  @Resource
  ThisBaseCodeImpl thisBaseCodeImpl;

  public BaseCode getBaseCode(String code) {
    if(code.equals("something")) return thisBaseCodeImpl;
    else //and so on
  }
}

I'm not sure if I understood your problem well, but in general spring dependencies have nothing to do here. Just write custom Factory class and return BaseCode implemetation depending on the reqObj.getcode().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top