使用 Cloud SDK Spring 原型在本地调用 BAPI 时找不到目的地

问题描述

我正在遵循 official documentation 在 SAP Cloud Platform 上和本地使用 Cloud SDK Spring 原型调用 BAPI。 Cloud SDK 版本为 3.35.0。

它在提供 RFC 目标的 SAP Cloud Platform 上运行良好,但在本地找不到目标。我完成了文档中的所有步骤。

以下是代码片段。

public List<CostCenter> getCostCenters() {
        
        System.setProperty("jco.destinations.dir","C:\\tools\\SAP\\destinationrfc");
        log.info(System.getProperty("jco.destinations.dir"));
        
        Destination destination = null;
        BapiRequestResult resultGetCostCenters = null;
        try {
            destination = DestinationAccessor.getDestination("s4x011rfc");
            log.info("Get destination successfully.");
            resultGetCostCenters = new BapiRequest("BAPI_COSTCENTER_GETLIST1")
                                       .withExporting("CONTROLLINGAREA","BAPI0012_GEN-CO_AREA","0010")
                                       .withTable("COSTCENTERLIST","BAPI0012_cclIST").end()
                                       .withTableAsReturn("BAPIRET2")
                                       .execute(destination);
            log.info("Get costcenters successfully.");
        } catch (Exception e) {
            e.printstacktrace();
            return null;
        }
        
        log.info("Start to get results.");
        //ResultElement re = resultGetCostCenters.get(0);
    
        return resultGetCostCenters.get("COSTCENTERLIST").getAsCollection().asList(CostCenter.class);
    }

我在文件夹“C:\tools\SAP\destinationrfc”中创建了一个 rfc 目标文件,并在我的代码中设置了系统属性

enter image description here

然后,我在 Eclipse 中使用 war 部署(集成了 Tomcat)启动了我的应用程序。应用启动成功后,我测试REST API触发BAPI调用,得到如下异常。

com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destination with name 's4x011rfc'.
    at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.lambda$getDestination$1(DestinationAccessor.java:121)
    at io.vavr.control.Try.getorElseThrow(Try.java:748)
    at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination(DestinationAccessor.java:117)
    at com.bosch.test.service.imp.CostCenterServiceImp.getCostCenters(CostCenterServiceImp.java:29)
    at com.bosch.test.controllers.CostCenterController.getCostCenters(CostCenterController.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.invocableHandlerMethod.doInvoke(invocableHandlerMethod.java:197)
    at org.springframework.web.method.support.invocableHandlerMethod.invokeForRequest(invocableHandlerMethod.java:141)
    at org.springframework.web.servlet.mvc.method.annotation.ServletinvocableHandlerMethod.invokeAndHandle(ServletinvocableHandlerMethod.java:106)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.dispatcherServlet.dodispatch(dispatcherServlet.java:1061)
    at org.springframework.web.servlet.dispatcherServlet.doService(dispatcherServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at com.sap.cloud.sdk.cloudplatform.servlet.RequestAccessorFilter.lambda$doFilter$1(RequestAccessorFilter.java:75)
    at com.sap.cloud.sdk.cloudplatform.thread.AbstractthreadcontextExecutor.lambda$execute$0(AbstractthreadcontextExecutor.java:317)
    at com.sap.cloud.sdk.cloudplatform.security.SecurityContextthreadcontextDecorator.lambda$decorateCallable$2(SecurityContextthreadcontextDecorator.java:51)
    at com.sap.cloud.sdk.cloudplatform.thread.threadcontextCallable.call(threadcontextCallable.java:225)
    at com.sap.cloud.sdk.cloudplatform.thread.AbstractthreadcontextExecutor.execute(AbstractthreadcontextExecutor.java:319)
    at com.sap.cloud.sdk.cloudplatform.servlet.RequestAccessorFilter.doFilter(RequestAccessorFilter.java:75)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:126)
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.access$000(ErrorPageFilter.java:64)
    at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:101)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
    at org.apache.tomcat.util.net.socketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.sap.cloud.sdk.cloudplatform.cache.CacheRuntimeException: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destination.
    at com.sap.cloud.sdk.cloudplatform.cache.CacheUtil.lambda$wrapCallableAsFunction$0(CacheUtil.java:45)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2343)
    at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2341)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2324)
    at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:108)
    at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:62)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.lambda$tryGetDestination$2ec57ad6$1(ScpCfDestinationLoader.java:96)
    at io.vavr.control.Try.of(Try.java:75)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.tryGetDestination(ScpCfDestinationLoader.java:95)
    at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationLoaderChain.tryGetDestination(DestinationLoaderChain.java:84)
    at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationLoader.tryGetDestination(DestinationLoader.java:36)
    at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.tryGetDestination(DestinationAccessor.java:139)
    ... 69 more
Caused by: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destination.
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationServiceAdapter.getDestinationConfigurationAsJson(ScpCfDestinationServiceAdapter.java:202)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.getDestinationConfigurationFromDestinationService(ScpCfDestinationLoader.java:214)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.getDestinationConfigurationByTenant(ScpCfDestinationLoader.java:158)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.getDestinationConfigurationByRetrievalStrategy(ScpCfDestinationLoader.java:131)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.loadAndParseDestination(ScpCfDestinationLoader.java:108)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationLoader.lambda$null$0(ScpCfDestinationLoader.java:98)
    at com.sap.cloud.sdk.cloudplatform.cache.CacheUtil.lambda$wrapCallableAsFunction$0(CacheUtil.java:42)
    ... 81 more
Caused by: com.sap.cloud.sdk.cloudplatform.resilience.ResilienceRuntimeException: com.sap.cloud.sdk.cloudplatform.thread.exception.threadcontextExecutionException: com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestFailedException: com.sap.cloud.sdk.cloudplatform.exception.CloudplatformException: Environment variable 'VCAP_SERVICES' is not defined.
    at com.sap.cloud.sdk.frameworks.resilience4j.Resilience4jdecorationStrategy.lambda$null$2(Resilience4jdecorationStrategy.java:182)
    at io.vavr.control.Try.onFailure(Try.java:659)
    at com.sap.cloud.sdk.frameworks.resilience4j.Resilience4jdecorationStrategy.lambda$decorateCallable$3(Resilience4jdecorationStrategy.java:181)
    at com.sap.cloud.sdk.cloudplatform.resilience.ResiliencedecorationStrategy.executeCallable(ResiliencedecorationStrategy.java:210)
    at com.sap.cloud.sdk.cloudplatform.resilience.ResilienceDecorator.executeCallable(ResilienceDecorator.java:197)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationServiceAdapter.getDestinationConfigurationAsJson(ScpCfDestinationServiceAdapter.java:189)
    ... 87 more
Caused by: com.sap.cloud.sdk.cloudplatform.thread.exception.threadcontextExecutionException: com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestFailedException: com.sap.cloud.sdk.cloudplatform.exception.CloudplatformException: Environment variable 'VCAP_SERVICES' is not defined.
    at com.sap.cloud.sdk.cloudplatform.thread.AbstractthreadcontextExecutor.execute(AbstractthreadcontextExecutor.java:299)
    at com.sap.cloud.sdk.frameworks.resilience4j.DefaultthreadcontextProvider.lambda$decorateCallable$0(DefaultthreadcontextProvider.java:26)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    ... 1 more
Caused by: com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestFailedException: com.sap.cloud.sdk.cloudplatform.exception.CloudplatformException: Environment variable 'VCAP_SERVICES' is not defined.
    at com.sap.cloud.sdk.cloudplatform.connectivity.ServiceCredentialsRetriever.getClientCredentials(ServiceCredentialsRetriever.java:35)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationServiceAdapter.getAccesstokenForDestinationService(ScpCfDestinationServiceAdapter.java:212)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationServiceAdapter.lambda$getDestinationConfigurationAsJson$0(ScpCfDestinationServiceAdapter.java:191)
    at com.sap.cloud.sdk.frameworks.resilience4j.Resilience4jdecorationStrategy.lambda$decorateCallable$1(Resilience4jdecorationStrategy.java:161)
    at com.sap.cloud.sdk.cloudplatform.security.SecurityContextthreadcontextDecorator.lambda$decorateCallable$2(SecurityContextthreadcontextDecorator.java:51)
    at com.sap.cloud.sdk.cloudplatform.thread.threadcontextCallable.call(threadcontextCallable.java:225)
    at com.sap.cloud.sdk.cloudplatform.thread.AbstractthreadcontextExecutor.execute(AbstractthreadcontextExecutor.java:293)
    ... 5 more
Caused by: com.sap.cloud.sdk.cloudplatform.exception.CloudplatformException: Environment variable 'VCAP_SERVICES' is not defined.
    at com.sap.cloud.sdk.cloudplatform.ScpCfCloudplatform.lambda$parseVcapServices$1(ScpCfCloudplatform.java:174)
    at io.vavr.control.Option.getorElseThrow(Option.java:351)
    at com.sap.cloud.sdk.cloudplatform.ScpCfCloudplatform.parseVcapServices(ScpCfCloudplatform.java:173)
    at com.sap.cloud.sdk.cloudplatform.ScpCfCloudplatform.getVcapServices(ScpCfCloudplatform.java:210)
    at com.sap.cloud.sdk.cloudplatform.ScpCfCloudplatform.getServiceCredentials(ScpCfCloudplatform.java:363)
    at com.sap.cloud.sdk.cloudplatform.ScpCfCloudplatform.getServiceCredentials(ScpCfCloudplatform.java:332)
    at com.sap.cloud.sdk.cloudplatform.connectivity.ServiceCredentialsRetriever.getClientCredentials(ServiceCredentialsRetriever.java:32)
    ... 11 more

更新

我对在环境变量中创建的目标进行了一些测试。它工作正常。除了文档中的配置,目标也应该在环境变量中创建。

目标定义在环境变量中非常简单。只需要目的地名称。请注意,目标名称应与您在本地目录中创建的代码和 jco 目标中使用的名称相同。

[{name: "s4x011rfc"}]

解决方法

我们扩展了有关从本地计算机运行 BAPI 调用的文档。 我们添加了一个关于如何维护环境变量 destinationssection,它让 SAP Cloud SDK 找到目标名称。