How to integrate Jdon Framework with Spring

  Jdon Framework can be integration with Spring, so we can use jdonframework's some new features in Spring application. although Jdon is based on PicoContainer that is difference from Spring IOC container, but by a integration class, jdon's component can inject into spring bean and spring bean can too be injected into jdon's component or service or consumer.

  Next step , we show how to write this integration class ?

  There are three hook class in Spring framework:

1. org.springframework.context.ApplicationContextAware:
its setApplicationContext method at first be invoked when spring startup.

2.org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
its postProcessBeanDefinitionRegistry and postProcessBeanFactory methods second be invoked;

3. org.springframework.context.ApplicationListener
its onApplicationEvent method will be noticed after Spring started successfully.

  We using these three class to inject Jdon and spring with each other. at first, we implements ApplicationContextAware and in its method we startup jdonFramework:

public class AppContextJdon implements ApplicationContextAware{

/**
* ApplicationContextAware's method
*
* at first run, startup Jdon Framework *
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;

  if (servletContext == null)
    if (applicationContext instanceof WebApplicationContext) {
      servletContext = ((WebApplicationContext) applicationContext).getServletContext();
      if (servletContext == null) {
        System.err.print("this class only fit for Spring Web Application");
        return;
      }

    }

  // start up jdon
  AppContextWrapper acw = new ServletContextWrapper(servletContext);
  ContainerFinder containerFinder = new ContainerFinderImp();
  containerWrapper = containerFinder.findContainer(acw);

  }

 

}

  And now we prepare to inject jdon component into spring by implements BeanDefinitionRegistryPostProcessor, here there are two method need override:

public class AppContextJdon implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor{

  ....

/**
* BeanDefinitionRegistryPostProcessor's method
*
* second run: check which spring bean that need injected from Jdon.
*
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

  for (String beanName : registry.getBeanDefinitionNames()) {
    String beanClassName = beanDefinition.getBeanClassName();
    try {
      Class beanClass = Class.forName(beanClassName);
      // large project need using Google Collection's lookup
      for (final Field field : ClassUtil.getAllDecaredFields(beanClass)) {
        if (field.isAnnotationPresent(Autowired.class)) {
          // prepare to inject jdon components into spring components with AutoWire;
          Object o = findBeanClassInJdon(field.getType());
          if (o != null) {
            neededJdonComponents.put(field.getName(), o);
          }
        }
      }
    } catch (ClassNotFoundException ex) {
        ex.printStackTrace();
    }
  }
}

/**
* BeanDefinitionRegistryPostProcessor's method
*
* third run: injecting the jdon component into Spring bean;
*
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
  this.factory = factory;

  //inject jdon components into spring components with AutoWire
  injectJdonToSpring();
}

 

//inject jdon components into spring components with AutoWire

public void injectJdonToSpring() {
  for (String name : neededJdonComponents.keySet()) {
    Object o = neededJdonComponents.get(name);
    if (!factory.containsBean(name))
      factory.registerSingleton(name, o);
    }
  }

}

  injectJdonToSpring() method will inject jdon components into spring components with @AutoWire, such as:


@Controller
@RequestMapping(value = "/contact")
public class UserController {

  @Autowired
  private UserRepository userRepository;

  @Autowired
  private RoleAssigner roleAssigner;

}

RoleAssigner is a component registered in Jdon, UserController is SpringMVC's REST controller, so UserController has dependency with com.jdon.domain.dci.RoleAssigner from JdonFramework, so by the method injectJdonToSpring() of above way, we can inject RoleAssigner into Spring's UserController.

  Next let us solve how to inject Spring into Jdon, this step must begin after Spring started and finished. so we implements Spring's ApplicationListener

public class AppContextJdon implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor, ApplicationListener {

  ....

/**
* ApplicationListener's method
*
* fouth run: after Spring all bean created and ApplicatioConext is ready .
*
* injecting Spring bean instances into jdon component.
*/
public void onApplicationEvent(ApplicationEvent ae) {
  if (ae instanceof ContextRefreshedEvent)
    injectSpringToJdon();
}

public void injectSpringToJdon() {
  AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
  RegistryDirectory registryDirectory = (RegistryDirectory)   containerWrapper.getRegistryDirectory();
  List<String> names = new ArrayList(registryDirectory.getComponentNames());
  for (String name : names) {
  Object o = containerWrapper.lookupOriginal(name);
  beanFactory.autowireBean(o);
  containerWrapper.register(name, o);

}

}

}

 

  This step let us can use Spring's component in jdon, such as @Consumer or @Component:


@Consumer("saveUser") // this is annotation from Jdon
public class UserSaveListener implements DomainEventHandler {

@Autowired //this is annotation from Spring
private UserRepository simpleJdbc;

public void onEvent(EventDisruptor event, boolean endOfBatch) throws Exception {...}

  When UserSaveListener was fired, and its simpleJdbc can use Spring's datasource or its JDBC template or other resource.

  At last ,donot forget configure this class into Spring XML:

<bean id="appContextJdon" class="com.jdon.spring.AppContextJdon"></bean>

AppContextJdon.java

SpringMVC+Jdon