【问题标题】:How to avoid a DestinationAccessException when sending a POST request to an OData service using SAP Cloud SDK version 3.2.0使用 SAP Cloud SDK 3.2.0 版向 OData 服务发送 POST 请求时如何避免 DestinationAccessException
【发布时间】:2020-06-15 04:51:20
【问题描述】:

我正在开发一个使用 SAP Cloud SDK 3.2.0 版的 Java 应用程序。我有一个使用 ResilienceDecorator 的 queueCallable 异步处理请求的端点;通过这项服务,创建了业务合作伙伴 (BP)。我正在使用 SoapUI 进行压力测试,有时在发送多个请求(例如 50 个请求)时,会生成 DestinationAccessException。我不知道这个问题的原因是什么,有人可以帮我找到解决方案吗?

有时会显示以下消息:

目标访问异常: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: javax.naming.NoInitialContextException:无法实例化类: org.apache.naming.java.javaURLContextFactory [根异常是 java.lang.ClassNotFoundException: org.apache.naming.java.javaURLContextFactory]

其他时候会显示以下消息:

DestinationAccessException:名称没有目的地 'ErpQueryEndpoint' 可以在任何注册的加载器中找到。

这是我的类 AccountController:

public class AccountController {

    @Autowired
    AccountBF accountBF;

    ...

    @RequestMapping(value = "/bp/create/extended", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<?> createBpExtended(@RequestBody BpCreateBasicRequest bpCreateRequest) throws IOException {

        Object bpCreateBasicResponse = accountBF.bpCreateExtended(bpCreateRequest);
        return ResponseEntity.ok(bpCreateBasicResponse);
    }
}

这是我的班级 AccountBFimpl:

public class AccountBFimpl implements AccountBF {

    private ResilienceConfiguration conf;

    ...

    public Object executeAsyncCall(BpCreateBasicRequest bpCreateRequest) {

        LogMessage logMessage = new LogMessage();

        ...

        JSONObject jsonResponse = null;

        try {

            ODataCreateRequestImpl createRequest = new ODataCreateRequestImpl("/sap/opu/odata/sap/ZAS_BP_CREATION_SRV",
            "BP_DATASet", bodyAsMap, null, null, null, headersAsMap, null, false, null, null, false);

            createRequest.execute("ErpQueryEndpoint");
            jsonResponse = new JSONObject();

        } catch (DestinationAccessException e ) {
            System.out.println("DestinationAccessException: "+e.getMessage());
            logMessage.setMessageContent("Creating the BP: " + bpCreateRequest.getNumeroId() + ". " +
            " DestinationAccessException: "+e.getMessage());
            writeMessageContent(logMessage);
        } catch (HttpServerErrorException e ) {
            System.out.println("HttpServerErrorException: " + e.getMessage());
            logMessage.setMessageContent("Creating the BP: " + bpCreateRequest.getNumeroId() + ". " +
            " HttpServerErrorException: "+e.getMessage());
            writeMessageContent(logMessage);
        } catch (Exception e ) {
            System.out.println("Exception: " + e.getMessage());
            logMessage.setMessageContent("Creating the BP: " + bpCreateRequest.getNumeroId() + ". " +
            " Exception: "+e.getMessage());
            writeMessageContent(logMessage);
        }

        ...

        return jsonResponse;
    }

    public Object bpCreateExtended(BpCreateBasicRequest bpCreateRequest) throws IOException {

        LogMessage logMessage = new LogMessage();
        logMessage.setMessageContent("Creating the BP: " + bpCreateRequest.getNumeroId() + ". " + "Entering the" +
        " bpCreateExtended method");
        writeMessageContent(logMessage);

        this.conf = ResilienceConfiguration.of(AccountBFimpl.class);
        Object response = null;

        CompletableFuture<Object> futureFirstStep = ResilienceDecorator.queueCallable(() ->
                executeAsyncCall(bpCreateRequest), conf);

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            logMessage.setMessageContent("Creating the BP: " + bpCreateRequest.getNumeroId() + ". " +
            " InterruptedException in sleep - bpCreateExtended: "+e.getMessage());
            writeMessageContent(logMessage);
        }

        logMessage.setMessageContent("After create the BP: " + bpCreateRequest.getNumeroId() + ". " + "Leaving the" +
        " bpCreateExtended method");
        writeMessageContent(logMessage);

        return (JSONObject) response;
    }
}

这是我的 pom.xml 的内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.atlantida.services</groupId>
    <artifactId>account</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>atlantida</name>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.sap.cloud.sdk</groupId>
                <artifactId>sdk-bom</artifactId>
                <version>3.2.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <properties>
        <java-version>1.8</java-version>
        <springframework.version>5.1.8.RELEASE</springframework.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.11</junit.version>
        <jackson-version>2.9.2</jackson-version>
        <lombok.version>1.18.8</lombok.version>

        <jcl.slf4j.version>1.7.12</jcl.slf4j.version>
        <logback.version>1.1.3</logback.version>

        <!-- if you are behind a proxy use the following two properties to configure your proxy. Default: None -->
        <proxy.host />
        <proxy.port />
        <non.proxy.hosts />

        <!-- Properties that are related to the SAP Cloud Platform. -->
        <scp.sdkVersion>1.44.12</scp.sdkVersion>

        <!-- this is the location of your local SAP CP Neo runtime -->
        <scp.sdkInstallPath>${project.basedir}/scp/sdk-${scp.sdkVersion}</scp.sdkInstallPath>
        <scp.sdkLocalServerContentPath>${project.basedir}/localServerContent</scp.sdkLocalServerContentPath>
        <scp.sdkErpEndpoint>${scp.sdkInstallPath}/server/config_master/service.destinations/destinations/ErpQueryEndpoint</scp.sdkErpEndpoint>

        <scp.sdkSymbolicLink>${project.basedir}/scp/sdk</scp.sdkSymbolicLink>
        <scp.sdkNeoCmdExtension>.sh</scp.sdkNeoCmdExtension>
        <scp.sdkNeoCmd>${scp.sdkInstallPath}/tools/neo${scp.sdkNeoCmdExtension}</scp.sdkNeoCmd>
        <scp.sdkLocalServer>${scp.sdkInstallPath}/server</scp.sdkLocalServer>

        <scp.skipInstallSdk>false</scp.skipInstallSdk>
        <scp.skipDeploy>false</scp.skipDeploy>
        <scp.skipPutDestination>false</scp.skipPutDestination>
        <scp.skipRestart>false</scp.skipRestart>
        <scp.skipRollingUpdate>true</scp.skipRollingUpdate>

        <scp.vmArguments />
        <scp.vmSize>lite</scp.vmSize>
        <scp.vmMinProcesses>1</scp.vmMinProcesses>
        <scp.vmMaxProcesses>1</scp.vmMaxProcesses>

        <scp.app />
        <scp.host />
        <scp.account />
        <scp.username />
        <scp.password />

        <!-- Required for SAP CP user session management and audit logging. -->
        <scp.warImportPackage>com.sap.security.auth.service,com.sap.security.um.service.api,com.sap.core.service.auditlog.impl,com.sap.cloud.auditlog,com.sap.cloud.auditlog.exception,com.sap.cloud.auditlog.extension</scp.warImportPackage>

        <!-- Defines whether the deployment is productive or not. -->
        <productive />
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson-version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!-- Bridge logging from JCL to SLF4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${jcl.slf4j.version}</version>
        </dependency>

        <!-- logback -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20190722</version>
        </dependency>

        <dependency>
            <groupId>com.sap.cloud.sdk.cloudplatform</groupId>
            <artifactId>scp-neo</artifactId>
        </dependency>

        <dependency>
            <groupId>com.sap.cloud.servicesdk</groupId>
            <artifactId>odatav2-connectivity-sdk3</artifactId>
            <version>1.36.2</version>
        </dependency>

        <dependency>
            <groupId>com.sap.cloud.sdk.cloudplatform</groupId>
            <artifactId>security-servlet</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.sap.cloud</groupId>
            <artifactId>neo-javaee7-wp-api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>atlantida</finalName>

        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-enforcer-plugin</artifactId>
                    <version>3.0.0-M2</version>
                    <executions>
                        <execution>
                            <id>SAP Cloud SDK Project Structure Checks</id>
                            <goals>
                                <goal>enforce</goal>
                            </goals>
                            <configuration>
                                <rules>
                                    <requireMavenVersion>
                                        <version>3.5</version>
                                    </requireMavenVersion>
                                    <requireJavaVersion>
                                        <version>${java.version}</version>
                                    </requireJavaVersion>
                                    <reactorModuleConvergence />
                                </rules>
                                <fail>true</fail>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                    <configuration>
                        <attachClasses>true</attachClasses>
                        <archive>
                            <manifestEntries>
                                <Version>${project.version}</Version>
                                <Import-Package>${scp.warImportPackage}</Import-Package>
                            </manifestEntries>
                        </archive>
                        <webResources>
                            <resources>
                                <filtering>true</filtering>
                                <directory>src/main/webapp</directory>
                                <includes>
                                    <include>**/web.xml</include>
                                </includes>
                            </resources>
                        </webResources>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>3.1.1</version>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>com.sap.cloud</groupId>
                                <artifactId>neo-javaee7-wp-sdk</artifactId>
                                <version>${scp.sdkVersion}</version>
                                <type>zip</type>
                                <overWrite>false</overWrite>
                                <outputDirectory>${scp.sdkInstallPath}</outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </plugin>

                <!-- Plugin for deployment to SAP Cloud Platform Neo. -->
                <plugin>
                    <groupId>com.sap.cloud</groupId>
                    <artifactId>neo-javaee7-wp-maven-plugin</artifactId>
                    <version>${scp.sdkVersion}</version>
                    <executions>
                        <execution>
                            <id>stop</id>
                            <phase>install</phase>
                            <goals>
                                <goal>stop</goal>
                            </goals>
                            <configuration>
                                <skip>${scp.skipRestart}</skip>
                            </configuration>
                        </execution>
                        <execution>
                            <id>deploy</id>
                            <phase>install</phase>
                            <goals>
                                <goal>deploy</goal>
                            </goals>
                            <configuration>
                                <skip>${scp.skipDeploy}</skip>
                                <vmArguments>${scp.vmArguments}</vmArguments>
                            </configuration>
                        </execution>
                        <execution>
                            <id>start</id>
                            <phase>install</phase>
                            <goals>
                                <goal>start</goal>
                            </goals>
                            <configuration>
                                <skip>${scp.skipRestart}</skip>
                            </configuration>
                        </execution>
                        <execution>
                            <id>rolling-update</id>
                            <phase>install</phase>
                            <goals>
                                <goal>rolling-update</goal>
                            </goals>
                            <configuration>
                                <skip>${scp.skipRollingUpdate}</skip>
                            </configuration>
                        </execution>
                    </executions>
                    <configuration>
                        <sdkInstallPath>${scp.sdkInstallPath}</sdkInstallPath>
                        <skip>${scp.skipInstallSdk}</skip>

                        <application>${scp.app}</application>
                        <source>${project.build.directory}/${project.build.finalName}.war</source>

                        <vmArguments>${scp.vmArguments}</vmArguments>
                        <size>${scp.vmSize}</size>
                        <minimumProcesses>${scp.vmMinProcesses}</minimumProcesses>
                        <maximumProcesses>${scp.vmMaxProcesses}</maximumProcesses>

                        <host>${scp.host}</host>
                        <account>${scp.account}</account>
                        <user>${scp.username}</user>
                        <password>${scp.password}</password>
                        <synchronous>true</synchronous>

                        <httpProxyHost>${proxy.host}</httpProxyHost>
                        <httpProxyPort>${proxy.port}</httpProxyPort>
                        <httpsProxyHost>${proxy.host}</httpsProxyHost>
                        <httpsProxyPort>${proxy.port}</httpsProxyPort>

                        <consoleCommand />
                        <consoleHttpProxyHost>${proxy.host}</consoleHttpProxyHost>
                        <consoleHttpProxyPort>${proxy.port}</consoleHttpProxyPort>
                        <consoleHttpsProxyHost>${proxy.host}</consoleHttpsProxyHost>
                        <consoleHttpsProxyPort>${proxy.port}</consoleHttpsProxyPort>

                        <dbsystem />
                        <dbSize />
                        <dbUser />
                    </configuration>
                </plugin>

                <!-- Plugin for deployment to local runtime of SAP Cloud Platform Neo. -->
                <plugin>
                    <groupId>com.sap.cloud.sdk.plugins</groupId>
                    <artifactId>scp-neo-maven-plugin</artifactId>
                    <version>3.2.0</version>
                    <configuration>
                        <sdkPlugin>neo-javaee7-wp-maven-plugin</sdkPlugin>
                        <sdkPluginVersion>${scp.sdkVersion}</sdkPluginVersion>
                        <sdkInstallPath>${scp.sdkInstallPath}</sdkInstallPath>
                        <sdkSymbolicLink>${scp.sdkSymbolicLink}</sdkSymbolicLink>
                        <sdkServerContentPath>${scp.sdkLocalServerContentPath}</sdkServerContentPath>
                        <source>${project.build.directory}/${project.build.finalName}.war</source>
                        <proxyHost>${proxy.host}</proxyHost>
                        <proxyPort>${proxy.port}</proxyPort>
                        <httpNonProxyHosts>${non.proxy.hosts}</httpNonProxyHosts>
                        <destinations>
                            <destination>
                                <path>${scp.sdkErpEndpoint}</path>
                                <username>achacon</username>
                                <password>*******</password>
                                <url>http://crmdev:4431</url>
                            </destination>
                        </destinations>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.sap.cloud.sdk.plugins</groupId>
                <artifactId>usage-analytics-maven-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>usage-analytics</goal>
                        </goals>
                        <configuration>
                            <skipUsageAnalytics>false</skipUsageAnalytics>
                            <generateSalt>true</generateSalt>
                                <!--
                                Note: A random salt is auto-generated once the project is built for the first time.
                                Please keep the generated salt in the POM file, for example, when pushing to git.

                                To learn more, visit: https://blogs.sap.com/2018/10/23/usage-analytics-s4sdk/
                                -->
                            <salt>5d5e4e1e8a5f05d547fe8880f65173bda150a670f91f3657b970eaa9e7a4d392</salt>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <!--
        Profiles that are used to set the Neo SDK "neo" command extension ("neo.sh" or "neo.cmd")
        -->
        <profile>
            <id>windows</id>
            <activation>
                <os>
                    <family>windows</family>
                </os>
            </activation>
            <properties>
                <scp.sdkNeoCmdExtension>.bat</scp.sdkNeoCmdExtension>
            </properties>
        </profile>
        <profile>
            <id>unix</id>
            <activation>
                <os>
                    <family>unix</family>
                </os>
            </activation>
            <properties>
                <scp.sdkNeoCmdExtension>.sh</scp.sdkNeoCmdExtension>
            </properties>
        </profile>

        <!-- Profile setting properties for deploying to the local SAP CP runtime. -->
        <profile>
            <id>local-deploy</id>
            <activation>
                <property>
                    <name>!scp.app</name>
                </property>
            </activation>
            <properties>
                <scp.skipInstallSdk>true</scp.skipInstallSdk>
                <scp.skipDeploy>true</scp.skipDeploy>
                <scp.skipPutDestination>true</scp.skipPutDestination>
                <scp.skipRestart>true</scp.skipRestart>
                <scp.skipRollingUpdate>true</scp.skipRollingUpdate>
            </properties>
        </profile>

        <!-- Profile setting properties for deploying a productive version to SAP CP. -->
        <profile>
            <id>scp-deploy</id>
            <activation>
                <property>
                    <name>productive</name>
                </property>
            </activation>
            <properties>
                <scp.skipInstallSdk>false</scp.skipInstallSdk>
                <scp.skipDeploy>true</scp.skipDeploy>
                <scp.skipPutDestination>false</scp.skipPutDestination>
                <scp.skipRestart>true</scp.skipRestart>
                <scp.skipRollingUpdate>false</scp.skipRollingUpdate>
            </properties>
        </profile>
    </profiles>
</project>

这是我的 ErpQueryEndpoint 文件:https://i.imgur.com/jIWsa4o.jpg

【问题讨论】:

    标签: java odata sap-cloud-platform sap-cloud-sdk


    【解决方案1】:

    感谢您提出的好问题。我注意到您使用的第一件事是使用已经过时的 SDK 版本,当前版本是 3.14.0,您目前使用的是 3.2.0。我们对每个版本都做了很多修复,我会推荐 切换到依赖项中的最新版本。看看我们的release notes

    关于弹性,很难准确说明负载测试为什么会失败,因为您通过调用非类型化请求构建器调用 SDK 团队未维护的非类型化请求构建器在相当低的级别上使用 SDK。对于 Odata V2 ODataCreateRequestImpl 是一个依赖项,并不意味着直接使用。我们只是为了边缘情况和方便而公开它。

    使用 SDK 的一种更可靠的方法是首先从您的服务定义生成虚拟数据模型,然后构建类型化请求。这些应该更多 可靠地实现并且更容易调试。

    我会看看我是否能找到更多关于这个案例的想法,同时更新 SDK 版本并检查你是否可以使用上面教程中提到的类型化请求构建器来进行 CRUD 将是一个好主意。

    如果您有任何其他细节可以更清楚地了解此案例,请随时分享。

    【讨论】:

    【解决方案2】:

    非常感谢您的回复,科瓦廖夫。我按照您的建议更新到 SAP Cloud SDK 版本 3.14.0,这是我的问题解决方案的一部分。

    升级到 SAP Cloud SDK 3.14.0 版本后,我尝试启动本地 SCP 部署,但出现错误。错误的解决方法是消除我的 pom.xml 的以下依赖:

    <dependency>
           <groupId>com.fasterxml.jackson.datatype</groupId>
           <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    

    另外,有必要在我的代码中替换以下指令:

    CompletableFuture<Object> futureFirstStep = ResilienceDecorator.queueCallable(() ->
                executeAsyncCall(bpCreateRequest), conf);
    

    有了这个指令:

    new Thread(() -> {
            some instruction;
        }).start();
    

    【讨论】:

    • 感谢您分享您的知识并为我们的@Aimee 提供帮助!版本之间的迁移确实并非每次都那么容易。我们通常每两周发布一个新的 SDK 版本,其中包含多个更新、修复等。我建议您不时更新您的依赖项。它将确保您不会因为大版本传播而面临一些重大更改或依赖问题。再次感谢您在此处发布您的发现!
    猜你喜欢
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多