春季同时通话

时间:2018-07-16 14:58:29

标签: java spring java-ee thread-safety

我认为我的问题是基于体系结构的,但不是很确定,因此我将尝试解释其现实情况。

我正在使用的软件是面向整体的,但与SOAP完全兼容。架构如下:

  • 基本概念是我们称为“ 事务”的概念,由其请求和响应(用于SOAP)定义。它还构建了可配置的业务逻辑(编辑文档,工作流等)
  • 我们在application-context.xml中为每个事务配置了1个bean(例如,PersonViewTransaction,PersonSelectTransaction,PersonEditTransaction)
  • 所有人都继承
    • 来自同一抽象类AbstractTransaction ,该类对所提供的请求实施控件
    • AbstractTransaction实现接口ITransaction
  • 我们构建了一个TransactionFactory,该工厂在任何使用beanId和请求的调用上,都会调用静态方法,该静态方法将为beanId标识的Transaction调用每个ITransaction的方法。

通过Web服务进行调用时,Servlet将调用该工厂并执行相同的逻辑,就像来自Web项目(Maven)的调用直接调用工厂一样。

换句话说:

ITransaction的定义

/**
 * The main interface defining what a transaction is.
 */
public interface ITransaction <Q extends GenericRequest, P extends GenericResponse> {

    P businessLogic(Q req);

    void executeControls(String transactionId, Q params, PerimetreAppel environnement)

    default void controleLicence() throws NassurCoreException
    {
        //TODO : contrôles de la licence à effectuer.
    }

    /**
     * Log before transaction
     */
    default void logEntree() throws NassurCoreException
    {
        //TODO to be implemented
    }

    /**
     * Log after transaction
     */
    default void logSortie() throws NassurCoreException
    {
        //TODO  to be implemented
    }

    /**
     * Checks that the user can call transaction
     */
    default void controleDroits() throws NassurCoreException
    {
        //TODO to be implemented
    }


    //...
    //Some other method not necessarily implemented in each transaction
}


/**
 * The abstract defining the default behaviour of a transaction
 */
public abstract class AbstractTransaction<Q extends GenericRequest, P extends GenericResponse> implements ITransaction<Q, P>{

    @Autowired
    private ControlService controlService;

    //.... some other autowired fields

    @Autowired
    protected UserDetailsService userDetailsService;

    protected String idTransaction;

    //Every transaction  must implement its own logic
    P businessLogic(Q params);


    @Override
    public void initialisation(String trId) 
    {
        this.idTransaction = trId;
    }


    @Override
    @Transactional
    public void executeControls(String transactionId, Q params, PerimetreAppel environnement)
    {
        //Some controls found from database, and executed 
        // A control consists of a combination between java checks and some Jruby executed from the Service
        List<SomeEntity> list = someEntityRepository.findByTransactionId(transactionId);
        for(SomeEntity  e : list){
            controlService.executeUnitControl(e, params);
        }
    }
}

交易

//Example Transaction
public class PersonViewTransaction extends AbstractTransaction<PersonViewRequest, PersonViewResponse>{

    @Override
    @Transactional
    public PersonViewResponse businessLogic(PersonViewRequest req){
        //...
    }
}


//Example Transaction
public class PersonEditTransaction extends AbstractTransaction<PersonEditRequest, PersonEditResponse> {

    @Override
    @Transactional
    public PersonEditResponse businessLogic(PersonEditRequest req){
        //...
    }
}


//Example Transaction
public class PersonSearchTransaction extends AbstractTransaction<PersonSearchRequest, PersonSearchResponse> {

    @Override
    @Transactional
    public PersonSearchResponse businessLogic(PersonSearchRequest req){
        //...
    }
}

那些Bean在application-context.xml中声明。

工厂

public class TransactionFactory
{
    public static GenericResponse executeTransaction(String id, GenericRequest req, HttpServletRequest request)
                    throws SomeExceptions
    {
        ServletContext servletCtx = request.getSession().getServletContext();
        ApplicationContext actualCtx = WebApplicationContextUtils.getWebApplicationContext(servletCtx);

        ITransaction tr = (ITransaction<GenericRequest, GenericResponse>) actualCtx.getBean(id.name());

        if (tr == null)
        {
            throw new Exception("internal Error", null);
        }
        return executeStack(id, tr, req, request);
    }



    private static GenericResponse executeStack(String id, ITransaction tr, GenericRequest req, HttpServletRequest request)
                    throws SomeExceptions
    {
        try
        {
            tr.initialisation(id);
            tr.controleLicence();
            tr.logEntree();
            tr.controleDroits();
            //...Several operations calling ITransaction

            tr.executeControls(id, req, provenance);

            //Calling transaction logic
            GenericResponse resp = tr.businessLogic(req);

            //...Many "after-business" other calls

            return resp;

        }
        catch (SomeExceptions e)
        {
            logger.error(e);
            throw e;
        }
    }
}

有些神秘,当在同一个transactionId上同时进行两个调用时,executeControls会抛出一些奇怪的返回值,好像两个执行都混在同一个bean中(对我来说,这似乎是线程安全的,但不是这样)确定...):

List<SomeEntity> list = someEntityRepository.findByTransactionId(transactionId);
for(SomeEntity  e : list){
    controlService.executeUnitControl(e, params);
}

executeUnitControl检查控件是否必须应用,并在需要时引发错误。更详细地说,这是基于一个以参数为参数的JRuby脚本,以构建可配置的和非基于Java的业务逻辑。

非常感谢您的帮助,如果有法国人,我随时愿意与他们聊天,以解释更多详细信息!

0 个答案:

没有答案