Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Panel

<beans xmlns="http://www.springframework.org/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

  xmlns:context="http://www.springframework.org/schema/context"

  xmlns:tx="http://www.springframework.org/schema/tx" 

  xmlns:aop="http://www.springframework.org/schema/aop"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

                      http://www.springframework.org/schema/tx&nbsp;

                      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

                      http://www.springframework.org/schema/aop

                      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

                      http://www.springframework.org/schema/context

                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">                     

  <!--

      Compose a CloudStack deployment with selected components here

  -->

  <bean id="databaseUpgradeChecker" />

  <bean id="management-server" class ="com.cloud.server.ManagementServerExtImpl" />

  <bean id="configuration-server" />

  <bean id="clusterManagerImpl" />

  <bean id="clusteredAgentManagerImpl" />

  <bean id="clusteredVirtualMachineManagerImpl" />

  <bean id="highAvailabilityManagerExtImpl" />

  <!- - bean id="bareMetalVmManagerImpl" / -->

  <bean id="userVmManagerImpl" />

  <bean id="consoleProxyManagerImpl" />

  <bean id="securityGroupManagerImpl2" />

  <bean id="premiumSecondaryStorageManagerImpl" />

  <bean id="randomlyIncreasingVMInstanceDaoImpl" /> 

  <!--

      Network Elements

  -->

  <bean id="Ovs">

    <property name="name" value="Ovs"/>

  </bean>

  <bean id="ExternalDhcpServer">

    <property name="name" value="ExternalDhcpServer"/>

  </bean>

  <bean id="BareMetal">

    <property name="name" value="BareMetal"/>

  </bean>

  <bean id="SecurityGroupProvider">

    <property name="name" value="SecurityGroupProvider"/>

  </bean>

  <bean id="VirtualRouter">

    <property name="name" value="VirtualRouter"/>

  </bean>

  <bean id="VpcVirtualRouter">

    <property name="name" value="VpcVirtualRouter"/>

  </bean>

  <bean id="NiciraNvp">

    <property name="name" value="NiciraNvp"/>

  </bean>

  ...

  

    ...

</beans> 

Panel

2. How to declare to be a CloudStack component

...

Panel
Wiki Markup
*@Component*

@Local(value=ClusterDao.class)

public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements ClusterDao {
\\

&nbsp; &nbsp; protected final SearchBuilder<ClusterVO> PodSearch;

&nbsp; &nbsp; protected final SearchBuilder<ClusterVO> HyTypeWithoutGuidSearch;

&nbsp; &nbsp; protected final SearchBuilder<ClusterVO> AvailHyperSearch;

&nbsp; &nbsp; protected final SearchBuilder<ClusterVO> ZoneSearch;

&nbsp; &nbsp; protected final SearchBuilder<ClusterVO> ZoneHyTypeSearch;
\\

&nbsp; &nbsp; private static final String GET_POD_CLUSTER_MAP_PREFIX = "SELECT pod_id, id FROM cloud.cluster WHERE cluster.id IN( ";

&nbsp; &nbsp; private static final String GET_POD_CLUSTER_MAP_SUFFIX = " )";

&nbsp; &nbsp; *@Inject*

&nbsp; &nbsp; protected HostPodDao \_hostPodDao;
\\

&nbsp; &nbsp; public ClusterDaoImpl() &nbsp;{ 
}

&nbsp; &nbsp;}

.&nbsp; &nbsp;// more content..

...

...

}
}\\ \\

\\

For most of low-level built-in components like DAOs, in Javelin practice, we use @Component annotation, since it saves us a lot of typing and can take advantage of Eclipse IDE's powerful refactoring and type-infer feature to help us coding. However, if you are developing high level components and you want to give flexibility for customer to choose to compose a particular CloudStack deployment, declare in componentContext.xml would be a better choice.

...

Panel
Wiki Markup
public abstract class BaseCmd &nbsp;{

&nbsp; &nbsp; ...static&nbsp;public StorageNetworkService \_storageNetworkService;

&nbsp; &nbsp; static&nbsp;public ConfigurationServiceTaggedResourceService \_configServicetaggedResourceService;

&nbsp; &nbsp; static&nbsp;public AccountServiceVpcService \_accountServicevpcService;

&nbsp; &nbsp; static&nbsp;public NetworkACLService \_networkACLService;

&nbsp; &nbsp; static&nbsp;public UserVmServiceSite2SiteVpnService \_userVmServices2sVpnService;

}&nbsp;..

...

}

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)

4. CloudStack Spring component coding conventions

4.1 Be aware of injection auto-wiring time and runtime

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 

4.2 Public constructors

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 

4.3 Component independent self initialization

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.

 

Panel
Wiki Markup

@Component

@Local(value={ConfigurationDao.class})

public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String> implements ConfigurationDao {

&nbsp; &nbsp;@PostConstruct

&nbsp; &nbsp; void initComponent() {

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try {

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; configure(this.getClass().getSimpleName(), this.getConfigParams());

&nbsp; &nbsp; &nbsp; &nbsp; } catch (ConfigurationException e) {

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s_logger.warn("Self configuration failed", e);

&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; }

}

4.4 Be aware of Spring proxy mode