cancel
Showing results for 
Search instead for 
Did you mean: 

CAP Java - odataV2 and odataV4 example for generation by mavin plugin

MR3
Explorer
0 Kudos
663

Hi, im working on a cap java project which uses standard odata v2 like API_PRODUCT_SRV and some own odata services . We are using fiori elements . We detect that the requested "search" function in fiori elements are not functional with OdataV2 . So we decide to change all odata service to v4. The standard service API_PRODUCT_SRV only exists as odata v2 -> when we see v4? Or isnt necessary to swtich to V4? Are existing some real world example where odata v2 AND odata v4 used together. I need examples where odatav2 and odataV4 clients are generated together with maven plugin( odata-generator-maven-plugin /odata-v4-generator-maven-plugin).

The question is not exposing V2 and V4 together. Thats simple done by the adapter.

I will have to generate the client java classes. I do this for the o2 services and also for v4. In V4 i have to override the V4 basepath because the edmx file doesnt contain this. Because im using 3 different o4 services i used 3 excution steps to do this. This is for me kind of strange, so i was looking for real world examples doing this in a better way?

<defaultBasePath>/sap/opu/odata4/sap/z7_dummyservice_o4/srvd/sap/z7_dummyservice/0001/
<defaultBasePath>/sap/opu/odata4/sap/z7_dummyserviceXY_o4/srvd/sap/z7_dummyservice/0001/

Kind Regards

Mario

Accepted Solutions (1)

Accepted Solutions (1)

MR3
Explorer
0 Kudos

Hi ,

yes i'm aware of the remote service feature and also i used it in the configuration.

I needed some time to figured out the solution which works for me.

1. step in pom.xml create plugin areas for odata-generator-maven-plugin odata-v4-generator-maven-plugin

-> so i can generate Odata V2 and V4.

Override the default paths if need. Important Exclude the edmx files which are not corresponding with the odata generator version.

E.g. -> here is the odata-v4-generator-maven-plugin so exclude all edmx files for OData V2

<configuration>
<defaultBasePath>/sap/opu/odata4/sap</defaultBasePath>
<inputDirectory>${project.basedir}/external</inputDirectory>
<excludes>*_O2.edmx,API_BUSINESS_PARTNER.edmx,API_PRODUCT_SRV.edmx</excludes>

2. Step specify the main suffix path -> i must do this because in the namespace of my OData V4 has some gateway.xy information

-> Also i do a workaround by add "/" as service. This is used to get a final url like this

/sap/opu/odata4/sap/z7test_list_o4/srvd/sap/z7test_list/0001//....

remote.services:

- name: "Z7TEST_LIST_O4"

destination:

name: "s4onprem_local"

suffix: "/sap/opu/odata4/sap/z7test_list_o4/srvd/sap/z7test_list/0001"

service: "/"

type: "odata-v4"

Answers (1)

Answers (1)

matthiaskuhr
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Mario,

addressing your questions individually:

  1. API_PRODUCT_SRV only exists as odata v2 -> when we see v4?
    -> Unfortunately, I don't know, maybe somebody else can answer this
  2. Or isnt necessary to swtich to V4?
    -> It's probably not useful to do so. The $search feature is an OData V4 feature, so it will only be supported by V4 services and V4 clients. Since the service is V2 anyway you have no choice but to use V2 when using the service. So if you switch to V4, you would have to translate it back to V2 to talk to the service anyway.

    -> But what is the semantics you want to achieve? Maybe you can realise the requirement with a V2 $filter expression...
  3. I will have to generate the client java classes.
    -> Why? The service is available in the SAP Cloud SDK as a pre-regenerated package. See https://api.sap.com/api/API_PRODUCT_SRV/cloud-sdk/Java
MR3
Explorer
0 Kudos

Hi,

refering to 2. -> by switching to V4 we will setup our own V4 Odata services inlcuding also a simpler version API_PRODUCT_SRV -> so we have real V4 Odatas.

What want we achieve . Just a simple fiori elements call like this:

/sap/opu/odata/sap/API_PRODUCT_SRV/$select=Product,ProductType&$search=4711&$skip=0&$top=10

But if we post this request by Fiori or Postman Tool we get

        <Error_Resolution>
<SAP_Transaction>For backend administrators: use ADT feed reader "SAP Gateway Error Log" or run transaction /IWFND/ERROR_LOG on SAP Gateway hub system and search for entries with the timestamp above for more details</SAP_Transaction>
<SAP_Note>See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)</SAP_Note>
</Error_Resolution>
A dirty idea was to change the call manual into, but for this we have to manipulate the cqn query in the cap backend. :
/sap/opu/odata/sap/API_PRODUCT_SRV/A_ProductDescription?$format=json&$filter=( substringof('Test', ProductDescription) eq true or substringof('4711', Product) eq true) and Language eq 'DE'

refering to 3. We generating new because we import the edmx files from the standard service API_PRODUCT_SRV and also our own edmx service metadata to use in our service defintion in the cds file. We have done this also for our own written Odatas.

using {API_PRODUCT_SRV as prod} from './external/API_PRODUCT_SRV.csn';
...
@cds.persistence.skip
@Capabilities : {
Insertable : false,
Updatable : false,
Deletable : false
}
@sap.searchable : 'true'
entity MyProduct as projection on prod.A_Product {
*
};

in the corresponding On-methods in the EventHandlerclass we just "receive" the CQN from the outside application(fiori) and run it.

In the hope that all expression are correct translated an will get an result. With the Standard DefaultService Class we cant use cqn only the hard coded methods like "getByKey" .. or something else. We dont wanted to analyze the CQN an translate it into the Javaclasses. This effort should do the cap framework with the direct cqn queries:

@On(entity = MyProduct_.CDS_NAME) public Result onMyProduct(final CdsReadEventContext context) { final CqnSelect selectQuery = context.getCqn(); final Result result = cqnServiceProduct.run(selectQuery);

... }

Because this failed i try now to use OData V4 . But here i have to change all the basepaths individually because the are not exists in the metadata of the services like in the V2. But i think my approach is a litte bit ugly so i was asking for examples where others used OData V4

<plugin>
<groupId>com.sap.cloud.sdk.datamodel</groupId>
<artifactId>odata-v4-generator-maven-plugin</artifactId>
<version>${sap-cloud-sdk-version}</version>
<executions>
<execution>
<id>generate-consumption1</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<defaultBasePath>/sap/opu/odata4/sap/zdummy1_o4/srvd/sap/zdummy1/0001/</defaultBasePath>
<inputDirectory>${project.basedir}/external</inputDirectory>
<outputDirectory>${project.build.directory}/vdm</outputDirectory>
<deleteOutputDirectory>false</deleteOutputDirectory>
<packageName>de.company.vdm.odata4</packageName>
<compileScope>COMPILE</compileScope>
<serviceMethodsPerEntitySet>true</serviceMethodsPerEntitySet>
<keepExistingSignatures>false</keepExistingSignatures>
<nameSource>NAME</nameSource>
</configuration>
</execution>
<execution>
<id>generate-consumption2</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<defaultBasePath>/sap/opu/odata4/sap/zdummy2_o4/srvd/sap/zdummy2/0001/</defaultBasePath>
<inputDirectory>${project.basedir}/external</inputDirectory>
<outputDirectory>${project.build.directory}/vdm</outputDirectory>
<deleteOutputDirectory>false</deleteOutputDirectory>
<packageName>de.company.vdm.odata4</packageName>
<compileScope>COMPILE</compileScope>
<serviceMethodsPerEntitySet>true</serviceMethodsPerEntitySet>
<keepExistingSignatures>false</keepExistingSignatures>
<nameSource>NAME</nameSource>
</configuration>
</execution>
<execution>
<id>generate-consumption3</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<defaultBasePath>/sap/opu/odata4/sap/zdummy3_o4/srvd/sap/zdummy_list/0001/</defaultBasePath>
<inputDirectory>${project.basedir}/external</inputDirectory>
<outputDirectory>${project.build.directory}/vdm</outputDirectory>
<deleteOutputDirectory>false</deleteOutputDirectory>
<packageName>de.company.vdm.odata4</packageName>
<compileScope>COMPILE</compileScope>
<serviceMethodsPerEntitySet>true</serviceMethodsPerEntitySet>
<keepExistingSignatures>false</keepExistingSignatures>
<nameSource>NAME</nameSource>
</configuration>
</execution>
</executions>
</plugin>
matthiaskuhr
Product and Topic Expert
Product and Topic Expert
0 Kudos

Are you aware of the Remote Services Feature? Maybe you can save some custom code with that.

Other than that I still don't quite understand why you are "re-packaging" the API_PRODUCT_SRV together with further custom EDMX definitions into a new file? What is the disadvantage of having 2 independent files? from which you generate 2 independent sets of Java classes? (or, only generate one since the SDK already brings the other)