cloud-sdk
cloud-sdk copied to clipboard
Direct call of stream (/$value) is not supported in generated v2 client and response header missing
Issue Description
When I generate v2 clients out of the EDMX file, I have no chance to request the binary data stream without requesting the entity first.
Important information: for example to receive a files content with a "file-service", I have to call this:
File file= fileService.withServicePath("FILE_SRV").getFileByKey("abc").executeRequest(sapHttpDestination);
InputStream i = file.fetchAsStream();
This are two HTTP requests, one to get the file, and one to get the /$value
.
In my case, the getFileByKey()
(FILESET_GET_ENTITY) is not implemented and I have to use this workaround to receive the files content:
final var file = new File("abc");
file.attachToService("FILE_SRV", sapHttpDestination);
InputStream i = file.fetchAsStream();
This is not very convenient and I would prefer to receive the fileService
via injection and receive the stream like this:
InputStream i = fileService.withServicePath("FILE_SRV").getFileByKey("abc").executeRequestForStream(sapHttpDestination);
Further, I have no chance to receive the HTTP response headers from the file /$value
request. I miss something like
file.getReponseHeaders()
Impact / Priority
My solution will be to not use the generated client but to code the HTTP request on my own. :-( (Only for this request.)
Error Message
(see above, something like Method FILESET_GET_ENTITY not implemented. if I call executeRequest(...)
)
Project Details
Dependencies and configuration
<dependency>
<groupId>com.sap.cloud.sdk.datamodel</groupId>
<artifactId>odata-core</artifactId>
<version>3.52.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>com.sap.cloud.sdk.datamodel</groupId>
<artifactId>odata-generator-maven-plugin</artifactId>
<version>3.52.0</version>
<executions>
<execution>
<id>generate-consumption</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputDirectory>${project.basedir}/sap/</inputDirectory>
<outputDirectory>${project.build.directory}/generated-sources/sap/</outputDirectory>
<deleteOutputDirectory>true</deleteOutputDirectory>
<packageName>com.abc.sap</packageName>
<defaultBasePath>sap/opu/odata/SAP/</defaultBasePath>
<compileScope>COMPILE</compileScope>
<serviceMethodsPerEntitySet>false</serviceMethodsPerEntitySet>
<nameSource>NAME</nameSource>
</configuration>
</execution>
</executions>
</plugin>
Checklist
- [x] Checked out the documentation and Stack Overflow
- [x] Description provided with all relevant information
- Attached debug logs
- Attached dependency tree
- [x] Provided the SAP Cloud SDK version & link to relevant source code
Hi @datze
You can get fileStream
and responseHeaders
in a single request by using the low-level Generic OData Client:
(ex. /FileService/FileCollection(id='abc')/$value?foo=bar
)
HttpDestination destination;
ODataEntityKey entityKey = new ODataEntityKey(ODataProtocol.V2).addKeyProperty("id", "abc")
ODataResourcePath resource = ODataResourcePath.of("FileCollection", entityKey).addSegment("$value");
ODataRequestReadByKey request = new ODataRequestReadByKey("FileService", resource, "?foo=bar", ODataProtocol.V2);
ODataRequestResultGeneric result = request.execute(HttpClientAccessor.getHttpClient(destination));
HttpResponse httpResponse = result.getHttpResponse();
Header[] responseHeaders = httpResponse .getAllHeaders();
try( InputStream fileStream = httpResponse.getEntity().getContent(); ) {
// do thing
}
The code is perfectly fine if used internally. Since it's a bit verbose we are currently not advertising it as much.
In case you prefer a one-liner / convenience API for your code fileService.withServicePath("FILE_SRV")
, then we'll consider a feature request. In that case please let us know the urgency, whether it's considered a blocker and when to expect such changes, if there is a schedule for you.
Alternatively you could just run the HTTP request yourself:
HttpDestination destination;
HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
HttpResponse httpResponse = httpClient.execute(new HttpGet("/FileService/FileCollection(id='abc')/$value"));
Header[] responseHeaders = httpResponse.getAllHeaders();
try( InputStream fileStream = httpResponse.getEntity().getContent(); ) {
// do thing
}
Kind regards Alexander