使用 SAP Cloud SDK 版本 3.2.0 向 OData 服务发送 POST 请求

Send POST request to OData service using SAP Cloud SDK version 3.2.0

我正在开发一个使用 SAP Cloud SDK 的应用程序。我之前使用 SAP Cloud SDK2.20.1 版本并发送了一个 POST 请求OData 服务。这是我用来发送 POST 请求:

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

    JSONObject jsonResponse = null;

    try {

        Map<String, Object> resp = createRequest.execute("ErpQueryEndpoint").asMap();
        jsonResponse = new JSONObject(resp);

    } catch(final ODataException e) {
        logger.error(e.getMessage(), e);
    }
    catch(final JSONException e) {
        logger.error(e.getMessage(), e);
    }

更新SAP Cloud SDK版本到3.2.0后,发送POST请求时出现如下错误:

Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient(Ljava/lang/String;)Lorg/apache/http/client/HttpClient;

我知道NoSuchMethodError的原因,调用ODataCreateRequestImpl[的execute方法时出错=58=] class,这个 class 在 com.sap.cloud.servicesdk:odatav2-connectivity:1.32.5.jar,并且在某个时候,当调用ODataCreateRequestImplclass的execute方法时,getHttpClient方法属于 com.sap.cloud.sdk.cloudplatform:cloudplatform-connectivity:3.2.0.jarHttpClientAccessor class 被调用,在这个class中,方法签名是public static HttpClient getHttpClient(@Nonnull HttpDestinationProperties destination),但是我得到的错误是因为这个方法在运行时的签名不同,它期望接收到一个String 参数而不是 HttpDestinationProperties.

我认为这是因为我不应该使用 ODataCreateRequestImpl class 来执行 POSTSAP Cloud SDK3.2.0 版中请求,尽管它在 2.20.1 版 中运行得很好].要从 版本 2.20.1 SAP Cloud SDK 迁移到 版本 3.2.0,我遵循了这些指南:

https://developers.sap.com/tutorials/s4sdk-migration-v3.html

https://blogs.sap.com/2019/08/01/migrate-to-version-3.0.0-of-the-sap-cloud-sdk-for-java/

有人可以帮我找到一个解决方案来执行对 OData 服务的 POST 请求吗?

这是我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>

        <!--&lt;!&ndash; https://mvnrepository.com/artifact/org.aspectj/aspectjtools &ndash;&gt;-->
        <!--<dependency>-->
        <!--<groupId>org.aspectj</groupId>-->
        <!--<artifactId>aspectjtools</artifactId>-->
        <!--<version>1.6.2</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.sdk.s4hana</groupId>
            <artifactId>s4hana-all</artifactId>
        </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>achacon100</password>
                                <url>http://sapcrmdev.adbancat.hn:8000</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>

一个有据可查的问题!不幸的是,Cloud SDK (com.sap.cloud.sdk.*) 中的 Service SDK (com.sap.cloud.servicesdk.*) 的附加版本似乎有一些之前未跟踪的内部依赖兼容性问题。

解法: 请尝试使用版本 3.9.0(或更高版本),而不是 Cloud SDK 版本 3.2.0。该问题已在该更新中得到修复。不用担心版本号的跳跃。我不希望您的应用程序代码出现兼容性问题。

或者,如果您确定要使用 3.2.0 版本,则可以在 POM 中手动添加兼容的 Service SDK 依赖版本,例如1.35.2(或更高版本)。

基本上有两种解决问题的方法:

  1. 通过我们的 Maven 插件创建您自己的 OData VDM。这样您就可以获得对服务的类型安全访问,而无需理会请求中的字符串。对于粗略的指南,您可以遵循 this guide,但请注意它是为 SDK 的版本 2 编写的。我们正在为版本 3 更新我们的博客文章,但目前您必须自己迁移它(应该不会比更改 groupId 和 artifactId 多得多)。
  2. 请改用 execute(HttpClient) 方法,例如那样:
    // altenative to create a Destination at runtime:
    // HttpDestination destination = DefaultHttpDestination.builder("https://www.google.de").build();
    HttpDestination destination = DestinationAccessor.getDestination("ErpQueryEndpoint").asHttp();
    HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
    Map<String, Object> resp = createRequest.execute(httpClient).asMap();
    
    这应该没有问题。