繁体   English   中英

使用SAP APM和S / 4HANA Cloud SDK时,OData导航会返回异常

[英]OData navigation returns exception when using SAP APM and S/4HANA Cloud SDK

我在SAP Web IDE Full-Stack中创建了一个APM业务应用程序。

S / 4HANA SDK使用S / 4HANA API读取业务伙伴。 自定义业务伙伴数据保留在SAP Cloud Platform HDI容器中。 业务伙伴实体与自定义实体具有0..1关联。

当自定义数据存在时,OData导航属性成功,但如果不存在,则返回空指针异常。 在任何一种情况下OData $ expand都不成功, error while trying to invoke the method java.util.Map.size() of a null object loaded from local variable 'm'返回error while trying to invoke the method java.util.Map.size() of a null object loaded from local variable 'm' 我可能错误地期望关联实体返回键属性的值,但不返回其他属性的值。

以下是数据模型,服务,业务伙伴操作,错误和日志。

数据模型CDS

entity BusinessPartner {
    Key BusinessPartner     : String(10);
    LastName                : String(40);
    FirstName               : String(40);
    status                  : Association to PartnerStatus;
}

entity PartnerStatus {
    Key BusinessPartner     : String(10);
    StatusConfirmed         : String(1);
}

服务CDS

service BusinessPartnerService {
    @cds.persistence.skip
    entity BusinessPartner @readonly as projection on s4c.BusinessPartner;

    entity PartnerStatus   @readonly as projection on s4c.PartnerStatus;
}

业务合作伙伴@Query和@Read

@Query(serviceName = "BusinessPartnerService", entity = "BusinessPartner")
public QueryResponse queryPartners(QueryRequest queryRequest) throws ServletException {
    final List<BusinessPartner> businessPartners;

    try {
        businessPartners = new DefaultBusinessPartnerService()
            .getAllBusinessPartner()
            .top(5)
            .execute();
    } catch (ODataException e) {
        throw new ServletException(e);
    }

    QueryResponse queryResponse = QueryResponse.setSuccess().setData(businessPartners).response();

    return queryResponse;
}

@Read(serviceName = "BusinessPartnerService", entity = "BusinessPartner")
public ReadResponse readPartner(ReadRequest readRequest) throws ServletException {
    String id = String.valueOf(readRequest.getKeys().get("BusinessPartner"));

    final BusinessPartner businessPartner;

    try {
        businessPartner = new DefaultBusinessPartnerService()
            .getBusinessPartnerByKey(id)
            .execute();
    } catch (ODataException e) {
        throw new ServletException(e);
    }

    ReadResponse readResponse = ReadResponse.setSuccess().setData(businessPartner).response();

    return readResponse;
}

错误

<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <code>CDSRuntimeException.NO_ENTITY_FOUND</code>
    <message xml:lang="en-US">No Entity found for the URL.</message>
</error>

日志

  2018-11-06T11:02:50.53-0500 [APP/PROC/WEB/0] OUT { "written_at":"2018-11-06T16:02:50.538Z","written_ts":1056610886992277,"component_id":"df464a53-1905-4c4b-bcc5-ef59761d2218","component_name":"ge2qqww1rr7SxSEK-apm-s4c-srv","DCComponent":"","organization_name":"-","component_type":"application","space_name":"dev","component_instance":"0","organization_id":"-","correlation_id":"-","CSNComponent":"","space_id":"5e8e1eb0-f9ca-40d8-8ba9-1880ca345628","Application":"ge2qqww1rr7SxSEK-apm-s4c-srv","container_id":"10.0.137.3","type":"log","logger":"com.sap.cloud.sdk.service.prov.v2.rt.core.CloudSDKODataErrorCallback","thread":"http-nio-0.0.0.0-3000-exec-2","level":"ERROR","categories":[],"msg":"Request URL: https://ge2qqww1rr7sxsek-apm-s4c-srv.cfapps.us10.hana.ondemand.com/odata/v2/BusinessPartnerService/BusinessPartner?$expand=status\nStatusCode:500","stacktrace":["java.lang.NullPointerException: while trying to invoke the method java.util.Map.size() of a null object loaded from local variable 'm'","\tat java.util.HashMap.putMapEntries(HashMap.java:501)","\tat java.util.HashMap.putAll(HashMap.java:785)","\tat com.sap.gateway.core.api.provider.data.BaseDataProvider.getSingleNavigationPathResult(BaseDataProvider.java:837)","\tat com.sap.gateway.core.api.provider.data.BaseDataProvider.readExpandedEntitySet(BaseDataProvider.java:915)","\tat com.sap.cloud.sdk.service.prov.v2.data.provider.CXSDataProvider.readExpandedEntitySet(CXSDataProvider.java:724)","\tat com.sap.cloud.sdk.service.prov.v2.rt.data.provider.HybridDataProvider.readExpandedEntitySet(HybridDataProvider.java:298)","\tat com.sap.gateway.core.api.provider.data.GenericODataProcessor.readEntitySet(GenericODataProcessor.java:895)","\tat org.apache.olingo.odata2.core.Dispatcher.dispatch(Dispatcher.java:77)","\tat org.apache.olingo.odata2.core.ODataRequestHandler.handle(ODataRequestHandler.java:131)","\tat org.apache.olingo.odata2.core.servlet.ODataServlet.handleRequest(ODataServlet.java:216)","\tat org.apache.olingo.odata2.core.servlet.ODataServlet.handle(ODataServlet.java:115)","\tat org.apache.olingo.odata2.core.servlet.ODataServlet.service(ODataServlet.java:85)","\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:742)","\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)","\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)","\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)","\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)","\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)","\tat com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.lambda$doFilter$0(RequestContextServletFilter.java:171)","\tat com.sap.cloud.sdk.cloudplatform.servlet.RequestContextCallable.call(RequestContextCallable.java:95)","\tat com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.doFilter(RequestContextServletFilter.java:173)","\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)","\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)","\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)","\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)","\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)","\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)","\tat com.sap.xs.java.valves.ErrorReportValve.invoke(ErrorReportValve.java:66)","\tat ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:191)","\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)","\tat com.sap.xs.jdbc.datasource.valve.JDBCValve.invoke(JDBCValve.java:62)","\tat com.sap.xs.security.UserInfoValve.invoke(UserInfoValve.java:19)","\tat com.sap.xs.statistics.tomcat.valve.RequestTracingValve.invoke(RequestTracingValve.java:43)","\tat com.sap.xs.logging.catalina.RuntimeInfoValve.invoke(RuntimeInfoValve.java:40)","\tat org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:685)","\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)","\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)","\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)","\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)","\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)","\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)","\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)","\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)","\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)","\tat java.lang.Thread.run(Thread.java:836)"] }

跨远程实体和本地实体的连接不会自动发生。 您必须使用关联实体PartnerStatus的Read操作手动实现此操作,该实体还指定导航BusinessPartner的源实体。 这个方法看起来如下(正如你所看到的,在这个例子中我总是返回虚拟数据):

@Read(serviceName = "BusinessPartnerService",
    entity = "PartnerStatus",
    sourceEntity = "BusinessPartner")
public ReadResponse readPartnerStatus(ReadRequest readRequest) throws ServletException {
    return ReadResponse.setSuccess().setData(
            ImmutableMap.of("BusinessPartner", "1003764", "StatusConfirmed", "X"))
        .response();
}

有关Read操作文档包含有关此概念的更多详细信息。

您现在需要访问数据库,例如,在处理程序中使用JPA(我没有尝试过)。 该文档有一节关于在自定义处理程序中使用JPA

我使用CDSDataSourceHandler来读取本地实体。

如果本地实体存在,则返回该实体。 如果本地实体不存在,则密钥将从源实体传递给实体。

private static Connection getConnection() {
    Connection conn = null;
    Context ctx;
    try {
        ctx = new InitialContext();
        conn = ((DataSource) ctx.lookup("java:comp/env/jdbc/java-hdi-container")).getConnection();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return conn;
}

@Read(serviceName = "BusinessPartnerService", entity = "PartnerStatus", sourceEntity = "BusinessPartner")
public ReadResponse readPartnerStatus(ReadRequest readRequest) {
    CDSDataSourceHandler dsHandler = DataSourceHandlerFactory.getInstance().getCDSHandler(getConnection(), readRequest.getEntityMetadata().getNamespace());

    EntityData ed = null;

    try {
        ed = dsHandler.executeRead(readRequest.getEntityMetadata().getName(), readRequest.getKeys(), readRequest.getEntityMetadata().getElementNames());
    } catch (CDSException e) { }

    if (ed != null) {
        return ReadResponse.setSuccess().setData(ed).response();

    } else {
        Map<String, Object> keys = readRequest.getKeys();
        Object keyObject = keys.get("BusinessPartner");
        String id = (String)keyObject;

        return ReadResponse.setSuccess().setData(ImmutableMap.of("BusinessPartner", id, "StatusConfirmed", "X")).response();
    }
}

然后OData $ expand对于实体和实体集都是成功的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM