DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.

DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
While we are refactoring CloudStack architecture, to lay out a better component oriented foundation, be open to tools that most developers are familiar with in Java community, we started to experience the usage of Apache Spring Framework, switching to Spring touches a lot of existing CloudStack codebase, however, it does not bring any business logic changes, but it does introduce changes that CloudStack developers need to be aware of.
CloudStack management server contains a collection of various components, components usually come with 4 different flavors, common framework components, manager components, adapter components and DAO components. After deploy time, CloudStack allows experienced customer to compose a customized setup through editing of configuration files. For CloudStack OSS (OpenSource) distribution, developers provides default configuration in applicationContext.xml.in and componentContext.xml.in, while for non-OSS distribution, the configuration will be provided in applicationContext.xml.in and nonossComponentContext.xml.in.
For all components that are mandatory and shared among both OSS distribution and non-OSS distribution, they should be declared in applicationContext.xml.in. Optional components, depends on whether or not they are specific to OSS or non-OSS distribution, they can appear in applicationContext.xml.in *and *componentContext.xml.in,* *either in one of the two files or the both.
If a certain component has different configuration for OSS and non-OSS distribution, it should go both to applicationContext.xml.in *and *componentContext.xml.in.
Use following flow to determine where your newly developed component should go
if (component is mandatory to OSS/non-OSS ) {
if( component shares common configuration in OSS/non-OSS ) {
put it in applicationContext.xml.in
} else {
put it in both componentContext.xml and nonossComponentContext.xml.in
}
} else {
if(component is for OSS only)
put it in componentContext.xml
else
put it in nonossComponentContext.xml
}
Spring component is nothing else more than a Java POJO object, once you've determined which file the component declaration should go using the flow at above. declaring it is fairly simple. Following gives an example
<bean id="configurationDaoImpl" / <bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl" />
ID of the component should be unique, as original configuration file are generated automatically from legacy code, it is usually named after the component class name.
One of the biggest advantage of switching to Spring is that Auto-wiring in Component has now become consistent. With previous ComponentLocator, there are a lot of places that have to use run-time wiring, for example, using ComponentLocator.getManager() to wire a reference to a manager component. The reason for developers to do so is that ComponentLocator does not fully resolved dependent injection for components, so when inter-component relationship becomes complex in a large system like CloudStack, lots of hacking ways rise up inside CloudStack codebase. Although it solves the immediate needs, but it also creates a lot of confusion for developers, the more components being involved into injection business, the more the system is tightly coupled with ComponentLocator itself.
Following is an example of such hacking way, inside BaseCmd class, developer tried to resolve all the references for every used components into static variables at BaseCmd. It also means that, when you add a new Command class to the system, you will have to remember to do something about your new service at BaseCmd class
public abstract class BaseCmd {
static public ConfigurationService _configService;
static public AccountService _accountService;
static public UserVmService _userVmService;
static public ManagementService _mgr;
// more code ...
}
With Spring, developer can now always use @Inject annotation to declare such reference. One of the top two reasons for us to try Spring experiments in Javelin, since with more complete dependency injection, it gives us a cleaner component coding practice. (the other top reason is that we have broader integration supports from many other third-party vendors, i.e., JUnit)
With previous ComponentLocator, we have many places that use run-time resolution for fields that can't be resolved automatically by ComponentLocator's injection, and in many of these cases, these run-time resolutions happen at object construction time. Under Spring, such way won't work any more. The reason is that when Spring constructs the component object, the added runtime logic running inside the constructor can not feed information back into Spring injection framework, it may cause the process to be broken. The solution to this issues is to always leave the object construction and auto-wiring work to Spring, and leave the component initialization later
Protected or private constructors may be a good coding practice to enforce certain usage pattern of the class. However, protected or private constructors are not friendly to Spring injection process. Please always use public constructors, for the same reason, if you POJO class wants to be Spring component, don't seal the class by putting final modifier to your class
It is a good practice to separate component construction and initialization, always try to make your component be self-dependable in initialization, self-dependable initialization means the component is able to initialize itself with the very minimal dependency to other component's initialization status. Use @PostConstruct to mark such initialization method for Spring to automatically call for you. Following is an example.
public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String> implements ConfigurationDao {
@PostConstruct void initComponent() { // more code... }
}
Although we've tried the best to cut the relationship to a component container inside component code, we still have very few places in framework components that need to be aware of existence of the component container, to avoid any strong binding to a particular container like Spring, we introduced a class called ComponentContext, it is responsible to bridge CloudStack component with a chosen component container (for now, it is Spring).
As a business logic component developer, you should avoid using any of the functions provided by ComponentContext, this can make the business component neutral to component container, since we now switched to standard javax @Inject auto-wiring annotation, it is even possible for your component to run in containers that are other than CloudStack
In CloudStack, some components are lifecyle sensitive, examples are those manager objects, adapter objects, to make lifecyle management more general and flexible, there are some TODO works to make component life-cycle management easier. We'll keep this topic updated in the community.