Real World Composites I – Visual Composer of this Series.
This blog is made in a tutorial style, so you should be able to follow all actions and do this on your own computer. What you need for this is:
- NetWeaver CE Developer Workplace
That is a complete NetWeaver AS Java and NetWeaver Developer Studio
(The download trial available from SDN does it)
- Configuration for services
- An ES workplace account
It’s free and can be ordered by Tips, Tricks & Must Knows about ES Workplace
What We Want to do
The application in the end should do the following: show a single page that lists employees of a company by name. An entry field allows to enter a search phrase.
Actually this was the first thing I wanted to do for this series of articles. As usual I stepped into the complicated thing first. Well, just listing employees of a company, what should be that complicated about it, correct? And I did find the right service for this.
It’s called EmployeeBasicDataByEmployeeQueryResponse_In. The challenge here was that it only accepts an id as input to search for an employee. Did I say already that I hate demos where you have to know an id out of the dark? I sat around too often typing in stupid combinations to even guess the pattern that was expected by the system.
Fortunately there is another service that accepts search terms with an asterisk. So you can easily find somebody using the search string “A*” (If there is any employee whose name starts with A). The service is called WorkagreementSimpleByElementsQueryResponse_In.
Easy to bring them together and then….
As you might see from the picture above, WorkAgreementSimpleblabla delivers a list in the end, while EmployeeBasicdada expects single record inputs. It does work nicely, as long as you like to see only the first line of the list sent to BasicData service and then click blindly through the list to get every time a single call and the value for a specific id that gives you no clue. Not really real world!
Composition with code
In part I we managed to get through without any coding. This stops here. Maybe the next version of Visual Composer will help us here (maybe next year I’ll do the same with Galaxy?) but today is today.
Yes, we will see code, but you will be amazed how easy that will be. What we want to do is to:
- make a composite service that accepts our search input (e.g. “A*”),
- puts it into the first service,
- gets the output,
- loops through the output to get single id’s,
- puts id into the second service,
- collects the output of the second service, and
- drops that collection as a result
Did I say collection? Oh, yes! Java Collections are a big deal in this game. We will go deeper into this later. As this stuff is more complicated than a completely visual environment, I’ll use a more step by step approach than I did in part I. Here we go:
Once the NetWeaver Developer Studio has started, you’ve got to change into the Composite Application Perspective (Window->Open Perspective->Other…->Choose Composite Application from list).
There you initialize a new project (File->New…->Project)
Even if you do not have a Development Infrastructure in place, you choose Development Infrastructure->Development Component. This will open up a local Development Component, which is necessary for Composites.
Clicking the Next button you see why you did so: There is a tree with a Composite Application Icon to choose. Do so and click Next again.
Now you have to select the software component. If you are not connected to a Development Infrastructure only “Local Development” appears and “My Components”, which you should choose. Click Next.
You now have to type in a name for the component. I chose getemployee.data for this.
Click Next and Finish.
Now there is happening a lot of generation in the background relax and enjoy your computer working a couple of seconds.
Before we can import any service, we need to make sure your Developer Studio is connected to a service repository. For this check Windows->Preferences->Web Services->Services Registry.
If you are using the ESR workplace on SDN, server names for both, UDDI Service and Classification Service should be set to sr.esworkplace.sap.com. As far as I remember the rest is there already as a default, but please check with the values in the picture:
If this is OK, you can go back to the Composition Application Explorer (that should be open in the upper left of the perspective). Open project getemployee.data in the tree and right click on the external icon.
Choose import Webservice. In the opening Window, set the radio button to Services Registry and click Next.
You will be asked for the services registry login. This is the general user/password combination of sruser/eswork123 for all esworkplace users.
In the following screen click on the Show Advanced link on the upper right side (I experienced a login error after this which could be solved by just clicking Back and from there Next without any further action, maybe some of you will see that too)
In the following tree you have to select BrowseByApplication->ERP Foundation->Business Partner Data Management->Employee and click Next.
Now click on EmployeeBasicDataByEmployeeQueryResponse_In and Finish.
You are asked about password and user again, but this time you are not connecting to a repository but to the registered server (which could be another system). Therefore this time you need to use the user and password you have been registered in your Enterprise Service account (In case you don’t have one, don’t worry – Tips, Tricks & Must Knows about ES Workplace, as it’s free for testing)
Now you have to do the same again with the second service we want to use searching for BrowseByApplication-> ERP HCM-> Personnel Administration -> Work Agreement. In the Found Service Definitione Window you have to choose WorkAgreementSimpleByElementsQueryResponse_In. Unfortunately you currently cannot do this in a single run through the wizard, as with two services clicked in the list it wont show any services. Whether this is a bug or a feature I also don’t know and will put this back to our development.
After this you can see the imported service in the external branch of your project.
Modelling a Service
Now we want to model another Service that will use the other two. Again this is a piece of cake:
Right click on the “modeled” branch in the project and choose New Application Service.
Lets name this service GetEmployeeData, which is the only thing you will be asked. The service is generated and opened. And how about a “Save all” at this point in time? (File menu, before you ask:)
In the right upper pane of the studios window your new service should now be open. If you cannot see it it should at least be in the tab pane and appear if you click on there. On the low end of the pane there is another tab list with the options General, Dependency, Operations, Datasource, and Implementation.
In the general tab there is a lot of administrative information about the generated service we currently don’t care about.
If you click on the Operations tab, we are where we want to do the next action. Here we define the operations we want to do in our service.
The operations we need in our service are three: one for every service to call and another one that will do the implemented action. Note that the third operation will be the only place where actual coding will happen. Everything else we will do via modeling.
On the Operations tab you see the list of operations on the upper part. This is currently empty, of course. Click the Add button behind it, select Custom operation and click Next.
Now we can enter some required data about the service. The first service should retrieve a list of IDs, so we want to call it GetIdList. You can also enter a description for documentation purpose. Set the Transaction type field to SUPPORTS, as this is the option for cases where it does not matter whethere there is transaction support or not. In our case we don’t care.
|If you want to know more about Transaction properties you can find this in the NetWeaver CE documentation|
Very important for us is to uncheck the Implemeted check box. Then click Finish. Why it is so important to uncheck this box we will see in a minute.
Do exactly the same with an operation called GetEmployee. This will be the operation that is called every time to get the employee data.
And third we need another operation called GetEmployeeListByQueryEmpName. This one will be exposed and actually used from the outside. Therefore it should be more descriptive. And this time we have to keep the Implemented check box checked. Then click Finished.
As you can see we now we have three operations where one will be implemented. If you now click on the Datasource tab in the lower section of the pane you’ll see that only those operations that are not implemented appear there, which will be important for mapping of our original services.
But before we do that, go back onto the Operations tab, as we have to do some additional work.
Click on the first operation and look at the lower section of the pane named Operation Parameters. Here we will define what the parameters are that go in and out of the operation.
The input parameter for the GetEmployee operation will be the employees ID (remember, that was the reason for the whole service, we have a list of IDs, but the service only accepts a single one).
If you now click through the left tree into [LocalDevelopment]getemployee.data-> external-> sap_xi_ea_hr_se_global-> DataTypes-> Simple Types, there is a type called EmployeeIDContent. Click on it and click on Add to Input (drag and drop would work also).
What Happens Here?
By importing the services we also imported all the data types that are necessary for their use. You can check in the project view where EmployeeBasicData appears. Going down that tree into the Input Parameters you will find the EmployeeID structure with the field simpleContent. This has type EmployeeIDContent and that is the field we need to fill up.
Open the Input Parameters back in the Operation parameters pane left side tree. You will see that we have a parameter inputParameter1 of type EmployeeIDcontent.
Double click in the parameters name and change it to EmpId. So it will be more descriptive once we have to use it in code.
Now we need to do the same for the Output parameter. This time we will choose from the Complex types the EmployeeBasicDataByEmployeeResponseMessage. Choose it and click Add to Output. This is the complete response as a single structure. We could define a less complex structure, but for the sake of simplicity I will do it this way in this example.
Change the output parameter name to EmployeeData.
Lets continue with operation GetIdList. As input parameter choose type MEDIUM_NameContent from simple types and name it FamilyName (doubleclick on the name, left tree). For output parameters choose complex type WorkAgreementSimpleByElementsResponseMessage and name it IdList. You can check in the project view that the types always correspond with those of the services to call.
And now the last service, where it gets a little bit more complex. GetEmployeeList… has one input parameter of type MEDIUM_NameContent. Lets name it PersonFamilyName. This is only passed through to the original service.
For the output parameter we need something more. Remember, we’re getting back the employee data piece by piece and what we actually want is a list of this data. This means we need a type that does not exist yet. Now here comes another cool thing for complex data types: we can actually model that data type.
Modeling a Data Type
Right-Click on the “modeled” branch of the project view and choose New Structure. Name it EmployeeList in the appearing window and click Finish. The newly defined structure opens in the project pane. As you can see there we have a tree of exsiting types and a list of structure fields there.
Open in the left side tree [LocalDevelopment]getemployee.data-> external-> sap_xi_ea_hr_se_global and choose EmployeeBasicDataByEmployeeResponseMessage.
Click on the Move-right button between the two sections. The attribute immediately changes into edit mode and you should rename it to EmployeeDataList. What we have now is nothing more then the output of EmployeeBasicData… But what we actualy wanted was a list of those. If you look at the Structure Fields once more you might recognize the Cardinality column and as smart as you are I’m sure the penny has dropped already. By changing the Cardinality of EmployeeDataList to 0..n this really becomes a list.
Isn’t that cool?
If I had to do this in Java plain code i’d go mad.
One more word about the data contained in here: As you see the list not only includes the Employee data, but also the Log data, which is Administrative data about the call. It contains for example error messages in case something went wrong. Obviously the call will return such data for every single call of the employee data inside our little service we just built. That is more information then you want. A more sophisticated version should shift that log data to the outside of the list and only transfer once. To make it short: we would have to implement error handling here.
The alternative would be to just drop this part of the structure and delete the log attribute, which I did in the first place. Unfortunately any service without Log info later is not recognized by Visual Composer as a valid structure and will not offer you automatic table handling for your structure.
Going back to the GetEmployeeData view pane, tab Operations you now can use the new data type as output parameter.
Click through the type tree [LocalDevelopment]getemployee.data-> modeled-> Data Types-> Complex Types and drag EmployeeList on the Output Parameters at the right side. Then rename the parameter with a double click on outputParameter1 to EmpList.
Mapping Services to Operations
Now click into the Datasource tab at the lower end of the pane.
Choose GetEmployee from the Target operations list and click on Create mapping.
Open the tree down to [LocalDevelopment]getemployee.data-> external-> sap_xi_ea_hr_se_global-> EmployeeBasicDataByEmployeeQueryResponse_In-> EmployeeBasicDataByEmployeeQueryResponse_In, choose the last value and click OK. The parameters for the chosen operation now appear in the Source operation pane.
Open the tree for the Input Parameters down to simpleContent and drag this value to the Target operation pane on the left side over EmpId. Drop it there.
Do the same with the Output Parameter EmployeeData. It is unimportant from which direction you draw, just drop on the right data type. After you’ve done this and opened the trees, you can see where the data is mapping like in the picture.
Now do this also for the second operation and map GetIdList with WorkAgreementSimpleByElementsQueryResponse_In (Same procedure as before). The Input Parameter FamilyName needs to be mapped with Source operation WorkAgreementSimpleByElementsQuery-> WorkagreementSimpleSelectionByElements-> SelectionByEmployee_FamilyName-> LowerBoundaryEmployee_FamilyName-> simpleContent.
And once again you map the Output Parameter IdList with WorkAgreementSimpleByElementsResponse.
An Introduction to Java Collections
Working with CAF Services needs some insight to Java Collections as this is the main data type that is used to map service strutctures. As I did not want to make this blog only for Java programmers, I think this needs a few words.
The definition is that Collections are objects that groups multiple elements into a single unit. For ABAP programmers the most equivalent thing is an internal table (and it’s ussed in a simmilar way)
If you want to know more see this tutorial from SUN Microsystems.
Next week we’ll continue with coding of the service and some configuration stuff….