Getting started with GWPA: Deep Insert with generated proxies (Java SE Toolkit)
In the meantime, as of July 2014, GWPA has been retired.
Please find more information here: SAP Gateway Developer Tools – Bridging the Past, Present and Future
In my Tutorial for using Java SE Toolkit with proxies, I’ve tried to explain how to use the Java SE Toolkit along with generated proxies. The Java SE Toolkit is provided by SAP NetWeaver Gateway Productivity Accelerator.
And I’ve tried to show how comfortable it is and that everything can be done with it.
However, I’ve been asked how to do deep insert with the toolkit, because it doesn’t provide support for it out of the box.
The good news is that it can be done.
The bad news, that it isn’t really comfortable. But still better than to do everything manually, deal with strings and xml parsing.
And here comes a proposal how the deep insert with Java SE Toolkit and proxies can be achieved.
Note: Sample code.
For your convenience, I’ve attached the result of this tutorial, the Java source, to this document.
Please find it below.
It is a text file that you can use for your convenience.
Instead of copying code snippets, you can view and copy the full coding to your IDE.
There’s only one thing you have to do: enter your user/pw for the sample service.
In order to follow this tutorial you need the following prerequisites
Install JavaSE toolkit along with GWPA
Furthermore you need to have access to an OData service.
In this tutorial we use the service ZGWSample_SRV, which is located on the Gateway Demo System, such that everybody can access it.
Please refer to the following document, where all links and details about all prerequisites are collected: Getting started with GWPA: Prerequisites
Finally, if you’ve never worked with the Java SE Toolkit and proxies, I recommend to go through my document Getting started with GWPA: Proxy Generation for Java SE Toolkit
This tutorial consists of the following 6 steps:
1) Create Project
2) Delete generated application code
3) Generate Proxy Classes
4) Write the deep insert code
1) Create Starter Application Project for Java SE Toolkit
Start your Eclipse and create a Starter Application Project
Eclipse main menu -> File -> New -> Project -> OData Development -> Starter Application Project
Enter a project name, e.g. DeepInsertTest
In the drop down box, select Java SE
Enter a package name, e.g. com.my.company.tests
Enter a name for the Java application class, e.g. DeepInsertTest
Select the template “Basic Application” and finish the wizard.
2) Delete generated application code
For this tutorial, we don’t need the generated code, because it doesn’t deal with proxies.
So we delete everything that is commented.
The result is an empty Java class.
3) Generate Proxy classes
Select your Java project and open the context menu.
Choose New -> other -> OData Development -> Service Proxy
In the drop-down, select Java SE. (If the drop down is empty, or doesn’t contain the entry, you have to install the Java SE toolkit, see Prerequisites)
Enter a new package name, e.g. com.my.company.proxies.gwsample
Choose “Remote Location” and enter the following URL of the Service which we will use:
Press Go and enter the credentials for the Gateway Demo System in the subsequent popup.
The wizard looks as follows:
Note: if you get an error related to SSL, please check again the prerequisites document which explains how to import a certificate into your Java VM.
The proxy classes are generated into the specified package.
4) Write the deep insert code
Open the class DeepInsertTest.java.
Create method initializeRestClient()
Create the method initializeRestClient() and configure the connection (see code sample)
Then, create a main() method which invokes the initializeRestClient() method.
Don’t forget to generate the import statements (Ctrl + O).
The sample code looks like this:
Create method deepInsertExample()
The specification of deep insert can be found here: http://www.odata.org/documentation/operations/#24_Creating_new_Entries
Within our tutorial, we’re using the service ZGWSAMPLE_SRV.
It provides a collection of BusinessPartners, with other words, a list of companies.
Each company has its own homepage, address, etc but is typically contacted via one or more contact persons.
These contacts are stored in a separate collection.
So, from the underlying model, we’re using this part:
The contacts that belong to a specific business partner can be reached via a NavigationLink, which is provided in the entry of a BusinessPartner.
You can verify this as follows:
Open the BusinessPartnerCollection in a browser:
Have a closer look at one entry:
Within the browser, we can use the $expand mechanism in order to see the data of both the BusinessPartner and the Contact(s) in only one request.
The URL is composed as follows:
To the collection, append ? and $expand= and the name of the <NavigationLink>
In our example, the URL would be the following:
You can see all the data of BusinessPartners and corresponding Contacts in one payload.
Now that we’ve explained the $expand, it is easier to understand the deep insert: it is the opposite.
A deep insert operation is a creation of a deep strcture (like the $expand presents a deep structure).
And now let’s continue with our tutorial and writing some code.
In the main() method, at the end, create an instance of the service proxy class:
ZGWSAMPLE_SRVService service = new ZGWSAMPLE_SRVService(restClient);
Then write the line that invokes the deep insert example method:
Since this method doesn’t exist, it is marked as error.
Place the cursor into this error and press Ctrl + 1
The quick fix proposals are displayed.
Select the entry “Create method …”
The method is generated and the error has disappeared.
Now let’s do some implementation.
Create method composeBusinessPartner
Let’s start from the end.
What we want to do is to invoke the creation of a new BusinessPartner instance.
This is done via:
BusinessPartner createdBusinessPartner = service.createBusinessPartnerCollectionEntry(templateBusinessPartner);
This means, in order to invoke this creation method, we have to provide the BusinessPartner object that we want to create via HTTP request.
OK, no problem, the BusinessPartner object can be easily created via constructor.
After creating the object via constructor, we have to set several properties.
Let’s move this code into a separate method, e.g.
OK, so far everything is just a normal creation code.
The sample code looks as follows:
We can test it and run the current state of the application.
The result should be an output on the Eclipse Console that prints the name of the created BusinessPartner
Create method composeContact()
What we want to achieve with the deep insert is to create a BusinessPartner and his Contacts within only one HTTP request.
So we have to add the so-called “inline data” to the BusinessPartner.
The “inline data” are the Contacts.
So we have to create the Contact objects.
In our example, let’s create only 1 Contact, in order to keep the code short.
We create a method which creates the Contact object and sets all required mandatory properties.
We don’t execute an HTTP request, i.e. we don’t invoke the method service.createContactCollectionEntry(), because this will be done at the end, together the method createBusinessPartnerCollectionEntry()
In our example, the composeContact() method looks as follows:
Now we can invoke the method composeContact() in the method deepInsertExample().
So, after we’ve created a Contact, we want to set it to the created BusinessPartner.
Therefore, we would like to invoke a method like BusinessPartner.addContact(newContact).
Such method doesn’t exist in the generated proxy.
And even if we create it, it doesn’t work.
It doesn’t work because there’s no support for deep insert in the Java SE Toolkit.
More concrete: no support for inline data on creation.
But we can hack it manually.
We’ve learned in the past tutorial, that we can change to the underlying layer, which deals with pure OData object model.
We need this now.
We need it for manually creating the “inline data”.
Create the InlineData
In order to understand the xml structure, we’ll look at how a deep insert request body looks in a REST client tool.
Note: within this tutorial, we’re working in xml format, as specified in the initialize method.
It could as well have been initialized with format JSON.
But we’ll see in the following description, that the code for deep insert is not generic, it works for XML only, since we have to do hard cast to the respective objects.
It would need more advanced code and changes to the generated proxies, in order to make the code more generic.
Here’s the relevant snippet of a request body for a deep insert of BusinessPartner and Contact.
The outer <entry> represents the BusinessPartner that will be created.
The inner <entry> represents the Contact and is located inside the <m:inline> tag
In our code, we have to create that structure as well.
No problem, every tag has its representation as Java object.
We do this coding in a separate method: composeInlineData().
This is how the sample code could look like:
Of course, this code sample is not productive code. The intention is only to show how a deep insert could be realized.
The final deepInsertExample()
Now we can add this method to deepInsertExample() and add some output for verifying the creation:
The last output prints a URL which can be copied to the browser and invoked. It provides a READ of the newly created BusinessPartner and an expand of the deeply inserted Contact.
Of course, that verification can as well be done in the Java coding.
Now you can run the application and verify the result.
We’ve proven that doing deep insert with Java SE Toolkit proxies is possible – although it isn’t natively supported.
The sample code is a bit dirty – it only intends to be a showcase and a starting point for anybody who would like to adapt it and productize it.
And it may also serve as starting point for any other exotic usage of the Java SE proxies.
As usual, I’m curious to see code snippets which you might provide in the comments-section of this posting.