在完成这个EJB单元测试框架的CMP的时候,核心应该就是成功使用Command模式,框架在初始化的时候会自动初始化需要使用的Entity Bean,包括Entity Bean之间的依赖关系,但是如果在初始化的时候,一个Entity Bean依赖另外一个还没有初始化的Entity Bean,而所依赖的那个Entity Bean又依赖这个Entity Bean,就会形成循环依赖。我使用Command模式,讲这个依赖关系放到一个Command里面,然后在一个Entity Bean的基本属性初始化完成以后再执行Command队列初始化那些关系,就不会形成循环依赖了。

代码如下:
package com.activereasoning.test.base;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.activereasoning.test.util.ClassUtil;
import com.activereasoning.test.util.CommandUtil;
import com.activereasoning.test.util.EJBUtil;
import com.activereasoning.test.util.StringUtil;
import com.activereasoning.test.util.ValueConverter;

public class InitEntityBeanCommand implements Command
{
    private static Logger log = LogManager.getLogger(InitEntityBeanCommand.class);

    private BeanInfo beanInfo;

    private Object pk;

    private Object object;

    private List setReferenceCommands = new ArrayList();

    private List setManyToManyCommands = new ArrayList();

    private List lookupEntityBeanCommands = new ArrayList();

    private List fields = new ArrayList();

    public InitEntityBeanCommand(BeanInfo beanInfo, Object pk)
    {
        this.beanInfo = beanInfo;
        this.pk = pk;
    }

    public void initCMPCommands(Object object, Map record)
    {
        setObject(object);
        String name = beanInfo.getShortName();
        Method[] methods = ClassUtil.getSetterMethods(object);
        for (int i = 0; i < methods.length; i++)
        {
            Method method = methods[i];
            String field = ClassUtil.getField(method);
            Class[] types = method.getParameterTypes();
            String column = null;
            String value = null;
            if (ClassUtil.isEntityBeanObject(types[0]))
            {//try to process entity type
                String targetBean = StringUtil.getShortClassName(types[0].getName());
                column = beanInfo.getFKColumn(targetBean);
                if (column == null)
                {
                    log.warn("Can not find target column for reference entity bean:" + targetBean + " of " + name);
                    continue;
                }
                value = (String) record.get(column);
                if (value == null)
                {
                    continue;
                }
                BeanInfo targetBeanInfo = EJBUtil.getBeanInfoByName(targetBean);
                if (targetBeanInfo == null)
                {
                    log.warn("Can not find target BeanInfo for " + targetBean);
                }
                else
                {
                    SetReferenceCommand command = new SetReferenceCommand(beanInfo, field, column, object, (Long) pk,
                            method, targetBeanInfo, value);
                    setReferenceCommands.add(command);
                }
            }
            else if (types[0].isAssignableFrom(Collection.class))
            {//try to process many to many relationship
                EJBRelationship ejbRelationship = beanInfo.getManyToManyRelationship(field);
                if (ejbRelationship != null)
                {
                    SetManyToManyCommand command = new SetManyToManyCommand(beanInfo, field, ejbRelationship);
                    setManyToManyCommands.add(command);
                    continue;
                }
                String manyBeanName = beanInfo.getManyToOneRelationship(field);
                if (manyBeanName != null)
                {
                    LookupEntityBeanCommand command = new LookupEntityBeanCommand(manyBeanName);
                    lookupEntityBeanCommands.add(command);
                }

            }
            else
            {//process normal type
                column = beanInfo.getFieldColumn(field);
                value = (String) record.get(column);
                if (column == null || value == null)
                {//ignore those null value or can not find corresponding database column
                    continue;
                }
                Object realValue = ValueConverter.getBeanValue(types[0], value);
                if (realValue != null)
                {
                    fields.add(new Object[]
                    { method, realValue });
                }
            }
        }
    }

    public void execute()
    {
        String name = beanInfo.getShortName();
        log.debug("Execute InitEntityBeanCommand for " + name + ", pk=" + pk);
        for (int i = 0; i < setReferenceCommands.size(); i++)
        {
            SetReferenceCommand command = (SetReferenceCommand) setReferenceCommands.get(i);
            command.setObject(object);
            CommandUtil.addCommand(CommandUtil.CMP, name, command);
        }
        for (int i = 0; i < setManyToManyCommands.size(); i++)
        {
            SetManyToManyCommand command = (SetManyToManyCommand) setManyToManyCommands.get(i);
            CommandUtil.addCommand(CommandUtil.CMP_LAZY_LOAD, name, command);
        }
        for (int i = 0; i < lookupEntityBeanCommands.size(); i++)
        {
            LookupEntityBeanCommand command = (LookupEntityBeanCommand) lookupEntityBeanCommands.get(i);
            CommandUtil.addCommand(CommandUtil.CMP_LAZY_LOAD, name, command);
        }
        try
        {
            for (int i = 0; i < fields.size(); i++)
            {
                Object[] objects = (Object[]) fields.get(i);
                ((Method) objects[0]).invoke(object, new Object[]
                { objects[1] });

            }
        }
        catch (Exception e)
        {
            log.error("Set entity bean fields error.", e);
        }
    }

    /**
     * @return the object
     */
    public Object getObject()
    {
        return object;
    }

    /**
     * @param object the object to set
     */
    public void setObject(Object object)
    {
        this.object = object;
    }

    public void add(Collection commands)
    {
    }

}

(Visited 23 times, 1 visits today)