Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 749
Alexander Torstling Avatar asked Apr 17 '26 11:04

Alexander Torstling


2 Answers

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.

like image 145
Jose Luis Martin Avatar answered Apr 22 '26 12:04

Jose Luis Martin


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.

like image 44
Solubris Avatar answered Apr 22 '26 12:04

Solubris