我在 S/4HANA Cloud 中创建了一个自定义业务对象,它包括一个父节点和一个子节点,还为 S/4HANA 自定义 OData 服务生成了 Java VDM。我将它与 SAP Cloud Platform SDK 结合起来进行服务开发(我再也找不到它的 SAP 帮助页面了)。
该方案是能够仅将新的子节点添加到现有的根节点。
当我尝试使用其他字段值对 ParentEntitySet()/childNavigation 执行 POST 操作时,我收到一条错误消息“方法调用无效:在非根实体 'YY1_CHILD_ENTITY' 上调用了 'CREATE' 方法。
我能做些什么来解决这个错误?
更新:
正如我所描述的,旧代码导致了错误
@Create(serviceName = "CrudService", entity = "ChildEntitySet", sourceEntity = "ParentEntitySet")
public CreateResponse createABC(CreateRequest createRequest) {
EntityData entity = createRequest.getData();
LeaveRequest response;
try {
response = new CreateChildCommand(new ErpConfigContext(), new DefaultService(), entity)
.execute();
} catch (HystrixBadRequestException e) {
return CreateResponse.setError(new ErrorResponseImpl(400, null, e.getMessage(), e.getCause(), null));
}
CreateResponse readResponse = CreateResponse.setSuccess().setData(response).response();
return readResponse;
}
新代码:错误消失了,但当我尝试使用导航发布子实体时出现新错误。
Inavalid Entity name: No entity with name ParentClass(guid'<parentKey>')/to_ChildEntity in the OData service
但是,当我使用与上述相同的 url 进行导航查询时,它工作得很好。只有用导航创建才有这个问题。
@Create(serviceName = "CrudService", entity = "ChildEntitySet", sourceEntity = "ParentEntitySet")
public CreateResponse createChild(CreateRequest createRequest) {
EntityData entity = createRequest.getData();
String parentKey = (String) createRequest.getSourceKeys().get(<parentKey>);
ChildClass response = new ChildClass();
Map<String, Object> childEntity = new HashMap<>();
try {
childEntity = entity.asMap();
response.setParentKey((String) entity.asMap().get(<parentKey>));
response.setText((String) entity.asMap().get("Text"));
response.setCreatedBy((String) entity.asMap().get("CreatedBy"));
response.setCreatedOn((Calendar) entity.asMap().get("CreatedOn"));
ParentClass parent = new ParentReadByKeyCommand(new ErpConfigContext(), parentKey)
.execute();
parent.createChildEntity(childEntity);
return CreateResponse.setSuccess().setData(response).response();
} catch (Exception e) {
// Return an instance of QueryResponse containing the error in case of failure
ErrorResponse errorResponse = ErrorResponse.getBuilder().setMessage(e.getMessage())
.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR).setCause(e).response();
return CreateResponse.setError(errorResponse);
}
}
下面的方法属于 ParentClass
public ChildClass createChildEntity(Map<String, Object> childEntity) throws ODataException {
if (erpConfigContext == null) {
throw new ODataException(ODataExceptionType.OTHER, "Failed to fetch related objects of type ChildClass.",
new IllegalStateException(
"Unable to execute OData query. The entity was created locally without an assigned ERP configuration context. This method is applicable only on entities which were retrieved or created using the OData VDM."));
}
final StringBuilder odataResourceUrl = new StringBuilder(getEntityCollection());
odataResourceUrl.append("(");
odataResourceUrl.append(ODataTypeValueSerializer.of(EdmSimpleTypeKind.Guid).toUri(<parentKey>));
odataResourceUrl.append(")/");
odataResourceUrl.append("to_ChildEntity");
final ODataCreateRequestBuilder builder = ODataCreateRequestBuilder
.withEntity(getEndpointUrl(), odataResourceUrl.toString()).withBodyAsMap(childEntity);
final ODataCreateRequest query = builder.build();
final ODataCreateResult result = query.execute(erpConfigContext);
final ChildClass entity = result.as(ChildClass.class);
entity.setErpConfigContext(erpConfigContext);
return entity;
}
我在用着
<parent>
<groupId>com.sap.cloud.servicesdk.prov</groupId>
<artifactId>projects-parent</artifactId>
<version>1.19.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.sap.cloud.s4hana</groupId>
<artifactId>sdk-parent</artifactId>
<version>1.11.1</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.sap.cloud.s4hana</groupId>
<artifactId>s4hana-all</artifactId>
<!-- <version>1.11.1</version> -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>