devxlogo

Bridging Configuration from Spring to Legacy Frameworks

Bridging Configuration from Spring to Legacy Frameworks

he Spring framework and its Plain Old Java Object (POJO)-based programming model enable you to inject collaborative objects into your classes via setter methods instead of looking them up inline via factory or locator classes. This approach is not only more intuitive, but it also drastically reduces the amount of code you need to write. In fact, Spring’s POJO-based programming model has proven to be a much better way to write, test, and assemble robust Java EE applications. But it works only if you configure your objects with Spring.

What happens when you combine Spring with an in-house legacy framework or Java EE technology such as EJBs or servlets? Suppose you have some objects defined outside of Spring (via your legacy services configuration), while others are defined and managed inside the Spring container. Can you extend Spring’s configuration to simplify and standardize your legacy framework? Maybe the biggest problem you face in trying to do so is that Spring and your legacy framework have competing bootstrapping processes. The Spring IOC container has a start-up process defined by the creation of a BeanFactory, and your legacy framework has its own rules for starting up servers.

The lazy solution would be to load Spring the first time a legacy service needs to refer to a bean. As an example of this approach, the following listing shows a typical combination of a legacy framework with Spring:

public class MyLegacyService extends SomePreIOC_AbstractService {    Pojo1 pojo1;    Pojo2 pojo2;    public void setPojo1(Pojo1 p1) {   pojo1 = p1;    }    public void setPojo2(Pojo2 p2) {   pojo2 = p2;    }    public MyLegacyService(String serviceName) {   super(serviceName);    }    // some pre-dependency injection configure method     // called by the legacy framework.    public void configure(ServiceConfig config) {   super.configure(config);   setPojo1((Pojo1) SpringSingleton.                    getBeanFactory().                    getBean("pojo.1"));   setPojo2((Pojo2) SpringSingleton.                    getBeanFactory().                    getBean("pojo.2"));    }}

The service MyLegacyService is created outside of Spring but needs to refer to Spring managed beans. Notice the explicit calls to access the specific Spring beans pojo.1 and pojo.2.

The following is the corresponding Spring configuration:

     "http://www.springframework.org/dtd/spring-beans.dtd">          

One subtle problem with this approach is that it is not clear how Spring managed objects can refer to your legacy service. Typically in Spring, you access objects created outside of the IOC container with a FactoryBean. This works extremely well for objects in a JNDI context, because the JNDI context typically will exist and be available prior to Spring starting. In the case of a legacy framework, however, you may not be able to guarantee that a FactoryBean will obtain an instance to an initialized legacy service. As an example, imagine the bean pojo.1 also needs a reference to its associated instance of MyLegacyService.

An ideal solution would be a configuration mechanism that supports your cyclical dependencies (MyLegacyService depending on Pojo1, and Pojo1 depending on MyLegacyService), yet remains flexible so that it doesn’t matter which bootstrapping process starts first. In other words, you wouldn’t need to care whether the external service is created first or it is referenced in Spring first.

The Oranjestad Spring project defines just such an extension to Spring. It allows you to register your legacy objects so that they can be configured via Spring. It does this using Spring’s namespaces extension point (see Sidebar 1. How Do External Beans Work?).

To use Oranjestad Spring, you first include an external namespace, which requires you to remove the standard DTD reference and import the external namespace in the beans tag:

xmlns:external="http://oranjestad.sourceforge.net/schema/external"  xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://oranjestad.sourceforge.net/schema/external
http://oranjestad.sourceforge.net/schema/external/external_1.0.xsd">

Then you add a Spring-style bean definition to define your configuration. The definition will be applied to your external legacy service:

<external:bean id="some.service" class="MyLegacyService">    …        external:bean>

Other than the external namespace qualifier, the revised XML configuration looks and acts exactly like a standard Spring definition and allows you to define your circular reference between the external legacy service (referred to as some.service in the Spring file) and pojo.1:

 id="some.service" class="MyLegacyService">    …            ref="some.service" /> 

The only other detail to cover is how your legacy service registers itself so that the Spring configuration can be applied to it. You accomplish this by using the oranjestad class SpringConfigurationBridge, which is called by the service after it has been initialized:

import oranjestad.spring.bootstrap.SpringConfigurationBridge;public class MyLegacyService extends SomePreIOC_AbstractService {    Pojo1 pojo1;    Pojo2 pojo2;    public void setPojo1(Pojo1 p1) {   pojo1 = p1;    }    public void setPojo2(Pojo2 p2) {   pojo2 = p2;    }    public MyLegacyService(String serviceName) {   super(serviceName);    }    // some pre-dependency injection configure method     // called by the legacy framework.    public void configure(ServiceConfig config) {   super.configure(config);	   SpringConfigurationBridge.            configure(this, "some.service");    }}

With the external bean approach, you have much greater flexibility with services that get created in an intertwined fashion. External beans do the following for your legacy system:

  • Handle all combinations of the legacy services starting before or after Spring
  • Extend dependency injection to your legacy system
  • Add some automatic annotation-based capabilities such as Spring’s JMX annotations for creating MBeans to work with your legacy service

This approach can greatly increase the adoption of Spring into a legacy framework by eliminating ugly bean lookups from the legacy service as well as by moving configuration from the legacy system to Spring.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist