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
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;

 public&nbsp; &nbsp; static&nbsp;public TaggedResourceService NetworkACLService \_taggedResourceServicenetworkACLService;

&nbsp; &nbsp; static&nbsp;public VpcService \_vpcService;

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

&nbsp; &nbsp; static&nbsp;public Site2SiteVpnService \_s2sVpnService;

}&nbsp;
}

With 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)

...

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 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

One side effect of using Spring is that component object created by Spring are not real object instantiated from you java class, but a proxy object in front of it. If your code heavily relies on runtime reflection info, your should be aware of such impact. During Javelin refactoring period, we've corrected a few cases that falls into this category. Examples can be found in ApiServer/ApiDispatcher. 

For regular business logic component developers, there are very few chances that you should be aware of, however, if do you encounter some problems and suspect that you have fallen into such traps, checkout ApiServer/ApiDispatcher for a reference solution.

4.5 Avoid creating run-time relationship with component container

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 always possible for your component to run in containers that are not CloudStack

5. Component lifecyle

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.