Навигация по OData возвращает исключение при использовании SAP APM и S / 4HANA Cloud SDK - PullRequest
0 голосов
/ 06 ноября 2018

Я создал бизнес-приложение APM в SAP Web IDE Full-Stack.

S / 4HANA SDK поддерживает деловые партнеры с помощью API S / 4HANA. Пользовательские данные деловых партнеров сохраняются в контейнере SAP Cloud Platform HDI. Сущность делового партнера имеет связь с пользовательской сущностью 0..1.

Свойство навигации OData успешно, когда пользовательские данные существуют, но возвращает исключение нулевого указателя, когда они не существуют. Расширение OData $ не является успешным в любом случае, возвращая 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

<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)"] }

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Я использовал 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 $ в таком случае успешно выполняется как для сущности, так и для набора сущностей.

0 голосов
/ 08 ноября 2018

Соединение через удаленный объект и локальный объект не происходит автоматически. Это необходимо реализовать вручную, используя операцию чтения для связанной сущности PartnerStatus, которая также указывает исходную сущность для навигации 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();
}

Документация об операции чтения содержит более подробную информацию об этой концепции.

Теперь вам необходимо получить доступ к базе данных, например, используя JPA (я не пробовал это) в обработчике. В документации есть раздел Использование JPA в пользовательских обработчиках .

...