方法扔了' org.springframework.beans.factory.support.scopenotactiveException'例外,当我尝试访问异步呼叫中的Singleton Bean时

发布于 2025-02-12 16:08:54 字数 25360 浏览 1 评论 0原文

我有一个httpbusinesscontext的豆子。它的范围是请求。现在,当我尝试在同一类中的一个异步调用中访问它时。它抛出方法抛出'org.springframework.beans.factory.support.scopenotactiveException'exception>我在这里需要帮助,我该如何解决。我是否需要更改httpbusinesscontext bean的范围,或者还有其他方法可以避免此问题。

这是我要获得的堆栈跟踪:

org.springframework.beans.factory.support.support.scopenotactiveException:错误创建使用名称'scopedtarget.gethttpthreadcontext':scope'的bean:s​​cope'请求'的请求'对于当前线程而言并不活跃;如果您打算从单身人士来看,请考虑为此豆定义范围代理;嵌套例外是Java.lang.IlgalStateException:找不到线程键的请求:您是在实际Web请求之外引用请求属性,还是在最初接收线程之外处理请求?如果您实际上在Web请求中运行并仍会收到此消息,则您的代码可能在dispatcherservlet之外运行:在这种情况下,请使用requestContextListener或requestContextFilter揭示当前请求。

这是httpBusinessContext类的Bean创建代码:

@Bean
@RequestScope
public HttpThreadBusinessContext getHttpThreadContext(){
    return new HttpThreadBusinessContext();
}

这是代码:

/**
 * This Service class will be used to handle business logic and complete processing if requestType = Details
 */
@Service
public class OrderDetailsRequestOperator {

    private static final RxWrappedLogger logger = RxWrappedLogger.getWrappedLogger(OrderDetailsRequestOperator.class);
    private static final AsyncRxWrappedLogger asyncWrappedLogger = AsyncRxWrappedLogger.getWrappedLogger(OrderDetailsRequestOperator.class);
    private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    @Autowired
    private HttpThreadBusinessContext httpThreadBusinessContext;

    @Autowired
    private SyncSapsRequestGateKeeper syncSapsRequestGateKeeper;

    @Autowired
    private FulfillmentOrderDtlRepo orderDtlRepo;

    @ManagedConfiguration
    private IRoutingConfig ccmManagedRoutingConfig;

    @Autowired
    private PatientRestrictionsCheckOperator patientRestrictionsCheckOperator;

    @Autowired
    private FulfillmentOrderRepo orderRepo;

    /**
     * Method to complete processing if requestType= Details
     * @param request
     * @return
     */

    public OrderDetailsFulfillmentResponse processRequest(OrderDetailsFulfillmentRequest request) {

        OrderDetailsFulfillmentResponse response;
        OrderDetailsStoreResponse storeResponse;
        /*
         * post to store for order details
         */
        try {
            //set readyForPickup to true to always filter rx's that are in resolution
            request.setIsReadyForPickup(true);
            //Calling Downstream Store api for OrderDetail.
            storeResponse = syncSapsRequestGateKeeper.retryAbleCall(request.getSiteNbr(),ccmManagedRoutingConfig.getOrderDetailsUrl(),getHttpHeaders(),
                    request,OrderDetailsStoreResponse.class);

            response = OrderInfoUtil.buildOrderDetailsResponseFromStoreResponse(storeResponse);
            response.setSiteNbr(request.getSiteNbr());
            response.setCountryCode(request.getCountryCode());
            response.setRequestType(request.getRequestType());
            //check if order details were found
            if(!storeResponse.getResponseCode().equals(Constants.SUCCESS_CODE)) {
                return response;
            }
            logger.info(httpThreadBusinessContext,"Data Fetched successfully from SAPs");

            //save order to fulfillment_order table with setting is_source_dotcom value
            updateOrderInFulfillmentTable(storeResponse.getSiteNbr(),storeResponse.getOrderId(),storeResponse.getOrderDetails().getIsSourceDotcom());
        } catch (Exception e) {
            logger.error(httpThreadBusinessContext,"Error occurred during request to store", e);
            return CommonUtil.getFailResponse(request, Constants.INTERNAL_SERVER_ERROR_CODE,Constants.PASSTHROUGH_REQUEST_ERROR_MSG);
        }

        /*
         * Save order details to database
         */
        try {
            logger.info(httpThreadBusinessContext,"Going to save Order-dtl to DB");
            //Saving Order-Detail to DB in case of Details request
            saveOrderDtlToDB(request,storeResponse);
            return response;

        } catch(Exception e) {
            logger.error(httpThreadBusinessContext,"Database error occurred saving Order Details", e);
            return CommonUtil.getFailResponse(request, Constants.INTERNAL_SERVER_ERROR_CODE, Constants.DATABASE_ERROR_MSG);
        }finally {
            //populate patient flags asynchronously
            if(storeResponse.getResponseCode().equals(Constants.SUCCESS_CODE)) {
                this.updatePatientRestrictionsFlagAsync(response, storeResponse);
                logger.debug(httpThreadBusinessContext, "patient restriction flgs updated");
            }
        }

    }
    /**
     * this method starts a process in a separate thread to update value of has_paper_reduction flag in order_dtl table
     * @param response
     * @param storeResponse
     */
    private void updatePatientRestrictionsFlagAsync(OrderDetailsFulfillmentResponse response, OrderDetailsStoreResponse storeResponse) {
        logger.info(httpThreadBusinessContext,"updatePatientRestrictionsFlagAsync process initiated!");

        // Run this process asynchronously so it can happen in the background
        //calculate and update value of has_paper_reduction flag in DB for each Patient/order-Seq-Nbr
        Integer storeNumber = response.getSiteNbr();
        if(storeResponse != null && storeResponse.getOrderDetails() != null
                && storeResponse.getOrderDetails().getPatientDetails() != null){

            for (StorePatientDetails patientDetails: storeResponse.getOrderDetails().getPatientDetails()) {
                Integer patientId = patientDetails.getPatientId();

                if(isIntegerGreaterThanZero(storeNumber) && isIntegerGreaterThanZero(patientId)){

                    // It should have been created in child thread instead oif parent thread as it is to be used in child thread.
                    final AsyncHttpThreadBusinessContext asyncHttpThreadBusinessContext = new AsyncHttpThreadBusinessContext(httpThreadBusinessContext);

                    CompletableFuture.supplyAsync(() -> {
                        return patientRestrictionsCheckOperator.getCloudPatientAPIResponse(storeNumber,patientId,asyncHttpThreadBusinessContext);
                    }).whenComplete((restrictList, t) -> {  // child thread

                        // solution 1 :

                        // issue : The issue is that both threads are accessing same variable of logger and httpcontext at same time.
                        // i) convert the logger and context into bean.
                        // ii) create new object of looger and context every time in child thread.
                        // iii) change the scope of logger and context bean and set logger and context in interceptor the star tof request.

                        // create
                        // it should be there
                        if (restrictList != null) {

                            //Update the order details in the database with Has_paper_reduction flag.
                            boolean hasPaperReduced = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.HAS_PAPER_REDUCED.getKey(), asyncHttpThreadBusinessContext);
                            boolean isLargeFontLeaflet = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.LARGER_FONT_LEAFLET.getKey(), asyncHttpThreadBusinessContext);
                            boolean isVisuallyImpaired = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.VISUALLY_IMPAIRED.getKey(), asyncHttpThreadBusinessContext);
                            
                            this.updatePatientRestrictionFlagsInOrderDtl(storeResponse.getOrderId(),storeNumber,
                                    patientDetails,hasPaperReduced,isLargeFontLeaflet,isVisuallyImpaired,asyncHttpThreadBusinessContext);
                            asyncWrappedLogger.info(asyncHttpThreadBusinessContext,"updatePatientRestrictionFlagsAsync process completed ! has_paper_reduced : "+ restrictList);
                            logger.info(httpThreadBusinessContext,"updatePatientRestrictionFlagsAsync process completed ! has_paper_reduced : "+ restrictList);

                        }
                    });
                }else{
                    logger.warn(httpThreadBusinessContext,"Error!Unable to compute patient restriction flags value,Invalid Params store:"+storeNumber+", patientID:"+patientId);
                }

            }
        }

    }

    /**
     * Save order Details to DB
     * @param request
     * @param response
     */
    private void saveOrderDtlToDB(OrderDetailsFulfillmentRequest request, OrderDetailsStoreResponse response) {
        //loop through length of patients list and nested loop through rx list.  saving records on rx level
        for (StorePatientDetails patient : response.getOrderDetails().getPatientDetails()) {
            for(StoreRxDetails rx : patient.getRxDetails()) {
                FulfillmentOrderDtlPK pk = new FulfillmentOrderDtlPK();
                pk.setOrderId(request.getOrderId());
                pk.setStoreNbr(request.getSiteNbr());
                pk.setOrderSeqNbr(rx.getOrderSeqNbr());
                FulfillmentOrderDtl row = new FulfillmentOrderDtl();
                row.setOrderDtlPk(pk);
                row.setPatientId(patient.getPatientId());
                row.setFillSeqNbr(rx.getFillSeqNbr());
                row.setRxFillId(rx.getRxFillId());
                row.setRxNbr(rx.getRxNbr());
                row.setRxPrice(rx.getRxPrice());
                row.setPaymentComplete(false); // auto set to false here
                row.setDrugCode(rx.getDrugCode());
                row.setIsRefill(rx.getIsRefill()); // set value of isRefill to true or false
                row.setPrefLangCode(response.getOrderDetails().getPatientDetails().get(0).getPreferredLanguage()); //only ever 1 patient in list
                if(response.getOrderDetails().getCardOnFile()) {
                    row.setPaymentTypeCode(1); //1 for charge card, 2 for pay at register
                }else {
                    row.setPaymentTypeCode(2);
                }
                orderDtlRepo.save(row);
            }
        }
    }

    /**
     * Update the order details in the database with Has_paper_reduction flag
     * @param orderId OrderID to be updated
     * @param siteNbr StoreNumber
     * @param patientDetails patient Details
     * @param hasPaperReduction
     * @param  asyncHttpThreadBusinessContext asyncHttpThreadBusinessContext containing business info
     */
    protected void updatePatientRestrictionFlagsInOrderDtl(String orderId,Integer siteNbr,StorePatientDetails patientDetails,Boolean hasPaperReduction,
                                                         Boolean isLargeFontLeaflet, Boolean isVisuallyImpaired, AsyncHttpThreadBusinessContext asyncHttpThreadBusinessContext) {
        try {
            List<FulfillmentOrderDtlPK> orderDetailsPkList = new ArrayList<>();
            if(patientDetails != null && !patientDetails.getRxDetails().isEmpty()){
                for (StoreRxDetails rxDetais : patientDetails.getRxDetails()) {
                    FulfillmentOrderDtlPK pk = new FulfillmentOrderDtlPK();
                    pk.setOrderId(orderId);
                    pk.setStoreNbr(siteNbr);
                    pk.setOrderSeqNbr(rxDetais.getOrderSeqNbr());
                    orderDetailsPkList.add(pk);
                }
            }

            List<FulfillmentOrderDtl> orderDtlRows = orderDtlRepo.findAllById(orderDetailsPkList);
            if (!orderDtlRows.isEmpty() && isUpdateRequired(hasPaperReduction, isLargeFontLeaflet, isVisuallyImpaired, orderDtlRows)){
                    orderDtlRepo.saveAll(orderDtlRows);
                    asyncWrappedLogger.info(asyncHttpThreadBusinessContext, "Order Details updated with patient restriction flags in Cloud SQL DB");
            }
        } catch (Exception e) {
            asyncWrappedLogger.error(asyncHttpThreadBusinessContext,"Unable to update has_paper_reduction flag in order details in DB",e);
        }
    }

    /**
     * Validates if it needs to update flags containing restriction type codes value in the database
     * @param hasPaperReduction flag to store restrictionTypeCode for paper reduction
     * @param isLargeFontLeaflet flag to store restrictionTypeCode for large font leaflet
     * @param isVisuallyImpaired flag to store restrictionTypeCode for visually Impaired indicator
     * @param  orderDtlRows order Details to be updated
     */
    private boolean isUpdateRequired(Boolean hasPaperReduction, Boolean isLargeFontLeaflet, Boolean isVisuallyImpaired, List<FulfillmentOrderDtl> orderDtlRows) {
        boolean updateRequired = false;
        for (FulfillmentOrderDtl orderDtl: orderDtlRows) {
            //update only if value is different
            if (orderDtl.getHasPaperReduction() == null ||
                    !orderDtl.getHasPaperReduction().equals(hasPaperReduction)) {
                orderDtl.setHasPaperReduction(hasPaperReduction);
                updateRequired = true;
            }
            if (orderDtl.getIsLargeFontLeaflet() == null ||
                    !orderDtl.getIsLargeFontLeaflet().equals(isLargeFontLeaflet)) {
                orderDtl.setIsLargeFontLeaflet(isLargeFontLeaflet);
                updateRequired = true;
            }
            if (orderDtl.getIsVisuallyImpaired() == null ||
                    !orderDtl.getIsVisuallyImpaired().equals(isVisuallyImpaired)) {
                orderDtl.setIsVisuallyImpaired(isVisuallyImpaired);
                updateRequired = true;
            }
        }
        return updateRequired;
    }

    /**
     * this method updates the value of isSourceDotCom column in order fulfillment table.
     * @param siteNbr
     * @param orderId
     * @param isSourceDotCom
     */
    public int updateOrderInFulfillmentTable(Integer siteNbr, String orderId, Boolean isSourceDotCom) {
        return orderRepo.updateisSourceDotcomColumnValue(isSourceDotCom,siteNbr, Integer.valueOf(orderId));

    }

}

这是 httpbusinesscontext 类。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import 

public class HttpThreadBusinessContext {
    private Integer siteNbr;
    private String countryCode;
    private String endPoint;
    private Object requestBody;
    private Map<String, Object> requestIdentifier = new HashMap();
    private String correlationId;

    public HttpThreadBusinessContext() {
    }

    public Integer getSiteNbr() {
        return this.siteNbr;
    }

    public String getCountryCode() {
        return this.countryCode;
    }

    public String getEndPoint() {
        return this.endPoint;
    }

    public Object getRequestBody() {
        return this.requestBody;
    }

    public Map<String, Object> getRequestIdentifier() {
        return this.requestIdentifier;
    }

    public String getCorrelationId() {
        return this.correlationId;
    }

    public void setSiteNbr(Integer siteNbr) {
        this.siteNbr = siteNbr;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public void setEndPoint(String endPoint) {
        this.endPoint = endPoint;
    }

    public void setRequestBody(Object requestBody) {
        this.requestBody = requestBody;
    }

    public void setRequestIdentifier(Map<String, Object> requestIdentifier) {
        this.requestIdentifier = requestIdentifier;
    }

    public void setCorrelationId(String correlationId) {
        this.correlationId = correlationId;
    }

    public InfoLog getInfoLog(String logMessage, Integer responseCode, String responseText) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage, Map<String, Object> infoLogIdentifier) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, infoLogIdentifier);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage, Integer responseCode, String responseText, Map<String, Object> infoLogIdentifier) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, infoLogIdentifier);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Exception exception) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, exception, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, (Exception)null, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, (Exception)null, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Exception exception) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Exception exception, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Exception exception, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, exception, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, (Exception)null, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object downStreamRequestPayload, Object downStreamResponsePayload) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, (Object)null, downStreamRequestPayload, downStreamResponsePayload, (String)null);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object identificationFields) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, identificationFields, (Object)null, (Object)null, (String)null);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object identificationFields, String responseDetail) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, identificationFields, (Object)null, (Object)null, responseDetail);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DebugLog getDebugLog(String message) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, (Map)null);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Object responseBody) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, responseBody, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, (Map)null);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Map<String, Object> debugLogIdentifier) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, debugLogIdentifier);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Object requestBody, Object responseBody, Map<String, Object> debugLogIdentifier) {
        DebugLog debugLog = new DebugLog(message, requestBody, requestBody, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, debugLogIdentifier);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public WarnLog getWarnLog(String message) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, (Exception)null, (Map)null);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public WarnLog getWarnLog(String message, Exception exception) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public WarnLog getWarnLog(String message, Exception exception, Map<String, Object> warnLogIdentifier) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, warnLogIdentifier);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public void setBusinessInfo(String countryCode, String endPoint, Integer siteNbr, Object requestPayload, Map<String, Object> requestIdentifier) {
        this.setCountryCode(countryCode);
        this.setEndPoint(endPoint);
        this.setSiteNbr(siteNbr);
        this.setRequestBody(requestPayload);
        this.setRequestIdentifier(requestIdentifier);
    }

    public void setBusinessInfo(String countryCode, String endPoint, Integer siteNbr, Map<String, Object> requestIdentifier) {
        this.setCountryCode(countryCode);
        this.setEndPoint(endPoint);
        this.setSiteNbr(siteNbr);
        this.setRequestIdentifier(requestIdentifier);
    }
}

I have a bean of Httpbusinesscontext at class level. It's scope is request. Now when I try to access it in one of the async call in same class. It throws Method threw 'org.springframework.beans.factory.support.ScopeNotActiveException' exception> I need help here that how can I resolve it. Do I need to change the scope of Httpbusinesscontext bean or there is some other way through which I can avoid this issue.

Here is the stack trace I am getting:

org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.getHttpThreadContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

Here is the code of bean creation for Httpbusinesscontext class:

@Bean
@RequestScope
public HttpThreadBusinessContext getHttpThreadContext(){
    return new HttpThreadBusinessContext();
}

Here is the code:

/**
 * This Service class will be used to handle business logic and complete processing if requestType = Details
 */
@Service
public class OrderDetailsRequestOperator {

    private static final RxWrappedLogger logger = RxWrappedLogger.getWrappedLogger(OrderDetailsRequestOperator.class);
    private static final AsyncRxWrappedLogger asyncWrappedLogger = AsyncRxWrappedLogger.getWrappedLogger(OrderDetailsRequestOperator.class);
    private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    @Autowired
    private HttpThreadBusinessContext httpThreadBusinessContext;

    @Autowired
    private SyncSapsRequestGateKeeper syncSapsRequestGateKeeper;

    @Autowired
    private FulfillmentOrderDtlRepo orderDtlRepo;

    @ManagedConfiguration
    private IRoutingConfig ccmManagedRoutingConfig;

    @Autowired
    private PatientRestrictionsCheckOperator patientRestrictionsCheckOperator;

    @Autowired
    private FulfillmentOrderRepo orderRepo;

    /**
     * Method to complete processing if requestType= Details
     * @param request
     * @return
     */

    public OrderDetailsFulfillmentResponse processRequest(OrderDetailsFulfillmentRequest request) {

        OrderDetailsFulfillmentResponse response;
        OrderDetailsStoreResponse storeResponse;
        /*
         * post to store for order details
         */
        try {
            //set readyForPickup to true to always filter rx's that are in resolution
            request.setIsReadyForPickup(true);
            //Calling Downstream Store api for OrderDetail.
            storeResponse = syncSapsRequestGateKeeper.retryAbleCall(request.getSiteNbr(),ccmManagedRoutingConfig.getOrderDetailsUrl(),getHttpHeaders(),
                    request,OrderDetailsStoreResponse.class);

            response = OrderInfoUtil.buildOrderDetailsResponseFromStoreResponse(storeResponse);
            response.setSiteNbr(request.getSiteNbr());
            response.setCountryCode(request.getCountryCode());
            response.setRequestType(request.getRequestType());
            //check if order details were found
            if(!storeResponse.getResponseCode().equals(Constants.SUCCESS_CODE)) {
                return response;
            }
            logger.info(httpThreadBusinessContext,"Data Fetched successfully from SAPs");

            //save order to fulfillment_order table with setting is_source_dotcom value
            updateOrderInFulfillmentTable(storeResponse.getSiteNbr(),storeResponse.getOrderId(),storeResponse.getOrderDetails().getIsSourceDotcom());
        } catch (Exception e) {
            logger.error(httpThreadBusinessContext,"Error occurred during request to store", e);
            return CommonUtil.getFailResponse(request, Constants.INTERNAL_SERVER_ERROR_CODE,Constants.PASSTHROUGH_REQUEST_ERROR_MSG);
        }

        /*
         * Save order details to database
         */
        try {
            logger.info(httpThreadBusinessContext,"Going to save Order-dtl to DB");
            //Saving Order-Detail to DB in case of Details request
            saveOrderDtlToDB(request,storeResponse);
            return response;

        } catch(Exception e) {
            logger.error(httpThreadBusinessContext,"Database error occurred saving Order Details", e);
            return CommonUtil.getFailResponse(request, Constants.INTERNAL_SERVER_ERROR_CODE, Constants.DATABASE_ERROR_MSG);
        }finally {
            //populate patient flags asynchronously
            if(storeResponse.getResponseCode().equals(Constants.SUCCESS_CODE)) {
                this.updatePatientRestrictionsFlagAsync(response, storeResponse);
                logger.debug(httpThreadBusinessContext, "patient restriction flgs updated");
            }
        }

    }
    /**
     * this method starts a process in a separate thread to update value of has_paper_reduction flag in order_dtl table
     * @param response
     * @param storeResponse
     */
    private void updatePatientRestrictionsFlagAsync(OrderDetailsFulfillmentResponse response, OrderDetailsStoreResponse storeResponse) {
        logger.info(httpThreadBusinessContext,"updatePatientRestrictionsFlagAsync process initiated!");

        // Run this process asynchronously so it can happen in the background
        //calculate and update value of has_paper_reduction flag in DB for each Patient/order-Seq-Nbr
        Integer storeNumber = response.getSiteNbr();
        if(storeResponse != null && storeResponse.getOrderDetails() != null
                && storeResponse.getOrderDetails().getPatientDetails() != null){

            for (StorePatientDetails patientDetails: storeResponse.getOrderDetails().getPatientDetails()) {
                Integer patientId = patientDetails.getPatientId();

                if(isIntegerGreaterThanZero(storeNumber) && isIntegerGreaterThanZero(patientId)){

                    // It should have been created in child thread instead oif parent thread as it is to be used in child thread.
                    final AsyncHttpThreadBusinessContext asyncHttpThreadBusinessContext = new AsyncHttpThreadBusinessContext(httpThreadBusinessContext);

                    CompletableFuture.supplyAsync(() -> {
                        return patientRestrictionsCheckOperator.getCloudPatientAPIResponse(storeNumber,patientId,asyncHttpThreadBusinessContext);
                    }).whenComplete((restrictList, t) -> {  // child thread

                        // solution 1 :

                        // issue : The issue is that both threads are accessing same variable of logger and httpcontext at same time.
                        // i) convert the logger and context into bean.
                        // ii) create new object of looger and context every time in child thread.
                        // iii) change the scope of logger and context bean and set logger and context in interceptor the star tof request.

                        // create
                        // it should be there
                        if (restrictList != null) {

                            //Update the order details in the database with Has_paper_reduction flag.
                            boolean hasPaperReduced = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.HAS_PAPER_REDUCED.getKey(), asyncHttpThreadBusinessContext);
                            boolean isLargeFontLeaflet = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.LARGER_FONT_LEAFLET.getKey(), asyncHttpThreadBusinessContext);
                            boolean isVisuallyImpaired = patientRestrictionsCheckOperator.filterListByFLag(restrictList, RestrictionCode.VISUALLY_IMPAIRED.getKey(), asyncHttpThreadBusinessContext);
                            
                            this.updatePatientRestrictionFlagsInOrderDtl(storeResponse.getOrderId(),storeNumber,
                                    patientDetails,hasPaperReduced,isLargeFontLeaflet,isVisuallyImpaired,asyncHttpThreadBusinessContext);
                            asyncWrappedLogger.info(asyncHttpThreadBusinessContext,"updatePatientRestrictionFlagsAsync process completed ! has_paper_reduced : "+ restrictList);
                            logger.info(httpThreadBusinessContext,"updatePatientRestrictionFlagsAsync process completed ! has_paper_reduced : "+ restrictList);

                        }
                    });
                }else{
                    logger.warn(httpThreadBusinessContext,"Error!Unable to compute patient restriction flags value,Invalid Params store:"+storeNumber+", patientID:"+patientId);
                }

            }
        }

    }

    /**
     * Save order Details to DB
     * @param request
     * @param response
     */
    private void saveOrderDtlToDB(OrderDetailsFulfillmentRequest request, OrderDetailsStoreResponse response) {
        //loop through length of patients list and nested loop through rx list.  saving records on rx level
        for (StorePatientDetails patient : response.getOrderDetails().getPatientDetails()) {
            for(StoreRxDetails rx : patient.getRxDetails()) {
                FulfillmentOrderDtlPK pk = new FulfillmentOrderDtlPK();
                pk.setOrderId(request.getOrderId());
                pk.setStoreNbr(request.getSiteNbr());
                pk.setOrderSeqNbr(rx.getOrderSeqNbr());
                FulfillmentOrderDtl row = new FulfillmentOrderDtl();
                row.setOrderDtlPk(pk);
                row.setPatientId(patient.getPatientId());
                row.setFillSeqNbr(rx.getFillSeqNbr());
                row.setRxFillId(rx.getRxFillId());
                row.setRxNbr(rx.getRxNbr());
                row.setRxPrice(rx.getRxPrice());
                row.setPaymentComplete(false); // auto set to false here
                row.setDrugCode(rx.getDrugCode());
                row.setIsRefill(rx.getIsRefill()); // set value of isRefill to true or false
                row.setPrefLangCode(response.getOrderDetails().getPatientDetails().get(0).getPreferredLanguage()); //only ever 1 patient in list
                if(response.getOrderDetails().getCardOnFile()) {
                    row.setPaymentTypeCode(1); //1 for charge card, 2 for pay at register
                }else {
                    row.setPaymentTypeCode(2);
                }
                orderDtlRepo.save(row);
            }
        }
    }

    /**
     * Update the order details in the database with Has_paper_reduction flag
     * @param orderId OrderID to be updated
     * @param siteNbr StoreNumber
     * @param patientDetails patient Details
     * @param hasPaperReduction
     * @param  asyncHttpThreadBusinessContext asyncHttpThreadBusinessContext containing business info
     */
    protected void updatePatientRestrictionFlagsInOrderDtl(String orderId,Integer siteNbr,StorePatientDetails patientDetails,Boolean hasPaperReduction,
                                                         Boolean isLargeFontLeaflet, Boolean isVisuallyImpaired, AsyncHttpThreadBusinessContext asyncHttpThreadBusinessContext) {
        try {
            List<FulfillmentOrderDtlPK> orderDetailsPkList = new ArrayList<>();
            if(patientDetails != null && !patientDetails.getRxDetails().isEmpty()){
                for (StoreRxDetails rxDetais : patientDetails.getRxDetails()) {
                    FulfillmentOrderDtlPK pk = new FulfillmentOrderDtlPK();
                    pk.setOrderId(orderId);
                    pk.setStoreNbr(siteNbr);
                    pk.setOrderSeqNbr(rxDetais.getOrderSeqNbr());
                    orderDetailsPkList.add(pk);
                }
            }

            List<FulfillmentOrderDtl> orderDtlRows = orderDtlRepo.findAllById(orderDetailsPkList);
            if (!orderDtlRows.isEmpty() && isUpdateRequired(hasPaperReduction, isLargeFontLeaflet, isVisuallyImpaired, orderDtlRows)){
                    orderDtlRepo.saveAll(orderDtlRows);
                    asyncWrappedLogger.info(asyncHttpThreadBusinessContext, "Order Details updated with patient restriction flags in Cloud SQL DB");
            }
        } catch (Exception e) {
            asyncWrappedLogger.error(asyncHttpThreadBusinessContext,"Unable to update has_paper_reduction flag in order details in DB",e);
        }
    }

    /**
     * Validates if it needs to update flags containing restriction type codes value in the database
     * @param hasPaperReduction flag to store restrictionTypeCode for paper reduction
     * @param isLargeFontLeaflet flag to store restrictionTypeCode for large font leaflet
     * @param isVisuallyImpaired flag to store restrictionTypeCode for visually Impaired indicator
     * @param  orderDtlRows order Details to be updated
     */
    private boolean isUpdateRequired(Boolean hasPaperReduction, Boolean isLargeFontLeaflet, Boolean isVisuallyImpaired, List<FulfillmentOrderDtl> orderDtlRows) {
        boolean updateRequired = false;
        for (FulfillmentOrderDtl orderDtl: orderDtlRows) {
            //update only if value is different
            if (orderDtl.getHasPaperReduction() == null ||
                    !orderDtl.getHasPaperReduction().equals(hasPaperReduction)) {
                orderDtl.setHasPaperReduction(hasPaperReduction);
                updateRequired = true;
            }
            if (orderDtl.getIsLargeFontLeaflet() == null ||
                    !orderDtl.getIsLargeFontLeaflet().equals(isLargeFontLeaflet)) {
                orderDtl.setIsLargeFontLeaflet(isLargeFontLeaflet);
                updateRequired = true;
            }
            if (orderDtl.getIsVisuallyImpaired() == null ||
                    !orderDtl.getIsVisuallyImpaired().equals(isVisuallyImpaired)) {
                orderDtl.setIsVisuallyImpaired(isVisuallyImpaired);
                updateRequired = true;
            }
        }
        return updateRequired;
    }

    /**
     * this method updates the value of isSourceDotCom column in order fulfillment table.
     * @param siteNbr
     * @param orderId
     * @param isSourceDotCom
     */
    public int updateOrderInFulfillmentTable(Integer siteNbr, String orderId, Boolean isSourceDotCom) {
        return orderRepo.updateisSourceDotcomColumnValue(isSourceDotCom,siteNbr, Integer.valueOf(orderId));

    }

}

and here is the HttpBusinessContext class.

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import 

public class HttpThreadBusinessContext {
    private Integer siteNbr;
    private String countryCode;
    private String endPoint;
    private Object requestBody;
    private Map<String, Object> requestIdentifier = new HashMap();
    private String correlationId;

    public HttpThreadBusinessContext() {
    }

    public Integer getSiteNbr() {
        return this.siteNbr;
    }

    public String getCountryCode() {
        return this.countryCode;
    }

    public String getEndPoint() {
        return this.endPoint;
    }

    public Object getRequestBody() {
        return this.requestBody;
    }

    public Map<String, Object> getRequestIdentifier() {
        return this.requestIdentifier;
    }

    public String getCorrelationId() {
        return this.correlationId;
    }

    public void setSiteNbr(Integer siteNbr) {
        this.siteNbr = siteNbr;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public void setEndPoint(String endPoint) {
        this.endPoint = endPoint;
    }

    public void setRequestBody(Object requestBody) {
        this.requestBody = requestBody;
    }

    public void setRequestIdentifier(Map<String, Object> requestIdentifier) {
        this.requestIdentifier = requestIdentifier;
    }

    public void setCorrelationId(String correlationId) {
        this.correlationId = correlationId;
    }

    public InfoLog getInfoLog(String logMessage, Integer responseCode, String responseText) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage, Map<String, Object> infoLogIdentifier) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, infoLogIdentifier);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public InfoLog getInfoLog(String logMessage, Integer responseCode, String responseText, Map<String, Object> infoLogIdentifier) {
        InfoLog infoLog = new InfoLog(logMessage, (Object)null, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, infoLogIdentifier);
        infoLog.setCorrelationId(this.correlationId);
        return infoLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Exception exception) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, exception, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, (Exception)null, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, (Exception)null, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Exception exception) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null, (Map)null);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Exception exception, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Exception exception, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, exception, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public ErrorLog getErrorLog(String logMessage, Integer responseCode, String responseText, Map<String, Object> errorLogIdentifier) {
        ErrorLog errorLog = new ErrorLog(logMessage, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, responseCode, responseText, (Map)null, (Exception)null, (Map)null, errorLogIdentifier);
        errorLog.setCorrelationId(this.correlationId);
        return errorLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object downStreamRequestPayload, Object downStreamResponsePayload) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, (Object)null, downStreamRequestPayload, downStreamResponsePayload, (String)null);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object identificationFields) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, identificationFields, (Object)null, (Object)null, (String)null);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DownStreamApiCallLog getDownStreamApiCallLog(long timeTakenInMillis, String downStreamApiUrl, Object identificationFields, String responseDetail) {
        DownStreamApiCallLog downStreamApiCallLog = new DownStreamApiCallLog((String)null, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, timeTakenInMillis, downStreamApiUrl, identificationFields, (Object)null, (Object)null, responseDetail);
        downStreamApiCallLog.setCorrelationId(this.correlationId);
        return downStreamApiCallLog;
    }

    public DebugLog getDebugLog(String message) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, (Map)null);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Object responseBody) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, responseBody, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, (Map)null);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Map<String, Object> debugLogIdentifier) {
        DebugLog debugLog = new DebugLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, debugLogIdentifier);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public DebugLog getDebugLog(String message, Object requestBody, Object responseBody, Map<String, Object> debugLogIdentifier) {
        DebugLog debugLog = new DebugLog(message, requestBody, requestBody, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (String)null, debugLogIdentifier);
        debugLog.setCorrelationId(this.correlationId);
        return debugLog;
    }

    public WarnLog getWarnLog(String message) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, (Exception)null, (Map)null);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public WarnLog getWarnLog(String message, Exception exception) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, (Map)null);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public WarnLog getWarnLog(String message, Exception exception, Map<String, Object> warnLogIdentifier) {
        WarnLog warnLog = new WarnLog(message, this.requestBody, (Object)null, this.siteNbr, this.countryCode, this.endPoint, this.requestIdentifier, (Integer)null, (String)null, (Map)null, exception, warnLogIdentifier);
        warnLog.setCorrelationId(this.correlationId);
        return warnLog;
    }

    public void setBusinessInfo(String countryCode, String endPoint, Integer siteNbr, Object requestPayload, Map<String, Object> requestIdentifier) {
        this.setCountryCode(countryCode);
        this.setEndPoint(endPoint);
        this.setSiteNbr(siteNbr);
        this.setRequestBody(requestPayload);
        this.setRequestIdentifier(requestIdentifier);
    }

    public void setBusinessInfo(String countryCode, String endPoint, Integer siteNbr, Map<String, Object> requestIdentifier) {
        this.setCountryCode(countryCode);
        this.setEndPoint(endPoint);
        this.setSiteNbr(siteNbr);
        this.setRequestIdentifier(requestIdentifier);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文