If you don’t want to use Maven to build the application, you can look up the dependencies of hibersap-core and hibersap-jco on Hibersap’s project site, under ”Dependency Convergence”: http://hibersap.org
We are going to write a small example application that will call the SAP function BAPI_SFLIGHT_GETLIST. This function is part of a demo application in SAP that implements a simplified flight-booking system.
This is the function module’s interface in SAP:
This function module takes some parameters that represent search criteria to look up flights in SAP’s database. The matching flights are returned in the FLIGHTLIST table, which contains information such as the airline carrier id, a flight connection code and departure/destination data. The RETURN structure may be filled by SAP with extra messages like errors, warnings, etc.
In this function, the import parameters are simple types, whereas the export and table parameter are complex data types (ABAP structures). The RETURN parameter is of type BAPIRET2, which is a standard structure that can be found in many function modules’ interfaces and that is not specific to this BAPI. See table 2.1.
Component name | Type | Description |
TYPE | Character | Message type: S Success, E Error, W Warning, |
I Info, A Abort | ||
ID | Character | Messages, message class |
NUMBER | Numeric character | Messages, message number |
MESSAGE | Character | Message text |
LOG_NO | Character | Application log: log number |
LOG_MSG_NO | Numeric character | Application log: Internal message serial number |
MESSAGE_V1 | Character | Messages, message variables |
MESSAGE_V2 | Character | Messages, message variables |
MESSAGE_V3 | Character | Messages, message variables |
MESSAGE_V4 | Character | Messages, message variables |
PARAMETER | Character | Parameter name |
ROW | 4-byte integer | Lines in parameter |
FIELD | Character | Field in parameter |
SYSTEM | Character | Logical system from which message originates |
The FLIGHTLIST table’s lines are of type BAPISFLIST which contains the following fields, as shown in table 2.2.
Component name | Type | Description |
CARRID | Character | Airline carrier ID |
CONNID | Numerical character | Flight connection code |
FLDATE | Date | Flight date |
AIRPFROM | Character | Airport of departure |
AIRPTO | Character | Destination airport |
DEPTIME | Time | Departure time |
SEATSMAX | 4-byte integer | Maximum capacity |
SEATSOCC | 4-byte integer | Occupied seats |
To call a function module from a Java application using Hibersap, we will write a BAPI class that acts as an adapter to JCo. The BAPI class is a simple Java class with a number of fields representing the BAPI’s import, export and table parameters. In case the BAPI parameter being a scalar parameter, the Java field itself is of a primitive Java type. In the case of a structure parameter, the Java field’s type has to be a complex type, too. A table parameter maps to an Array or a Collection of a complex type.
All setup related to the function module’s interface is done via Java annotations. A BAPI class is defined using the Hibersap class annotation @Bapi, which has a name argument specifying the name of the SAP function module we want to call. (All Hibersap annotations can be found in the package org.hibersap.annotations.)
The Java fields that will be mapped to the function module’s parameters are annotated with the @Import, @Export or @Table annotations to tell Hibersap which kind of parameter it should handle. Additionally, we have to specify the function module’s field name to which it relates, using the @Parameter annotation. The @Parameter’s second argument, type, tells Hibersap if the parameter has a simple or a complex structure type. The enumeration ParameterType defines possible values, the default type for element type being SIMPLE. In most cases we have to specify a parameter’s name only. Since table parameters always represent a table of complex types, any parameter type argument will be ignored by Hibersap.
The Java type of each simple field is related to the SAP field’s data type. Hibersap relies on the Java Connector’s conversion scheme as shown in table 5.1.
The @Convert annotation on the field afternoon in the listing above tells Hibersap to use a Converter of type BooleanConverter to convert the parameter AFTERNOON which is a character field of length 1 to a Java boolean value. See section 5.1 on how to implement custom Converters.
To conclude the example, we write a constructor which takes all the import parameters as arguments, initializing the corresponding fields.
Finally, we should add a getter method for each field. Hibersap itself does not need setter methods, because all fields are set using reflection. We could of course add additional fields and methods if needed.
______________________________________________________________________________________________
Note — There is one constraint in the current version of Hibersap you should take into account: The mapping between SAP parameters and Java classes works as expected only if the SAP function module complies to the BAPI standard, this means:
______________________________________________________________________________________________
There are two more classes we have to write: One for the complex export parameter RETURN, which is named BapiRet2, after the SAP data type. It is another annotated simple Java class with fields related to some of the function module’s parameter. To keep the example simple, we do not map all the fields of the RETURN parameter.
The class is annotated with @BapiStructure to tell Hibersap that it maps to a complex parameter on the SAP side. Each particular field is annotated with the already known @Parameter annotation that defines the name of the corresponding structure field. The BapiRet2 class is already part of Hibersap, since this structure is used by a lot of SAP function modules. This means, you don’t have to implement it.
The second class we need to implement is a Java class that Hibersap will map to each row in the table parameter FLIGHTLIST, which in our example is simply called Flight. The table FLIGHTLIST will be filled by SAP with the flight information matching our request.
Please note that the method getDepartureTime() does not simply return the field departureTime but calls a utility method DateUtil.joinDateAndTime(). This is done here because ABAP – unlike Java – does not have a data type that contains date and time. In ABAP such a timestamp is separated into two fields, one of type Date, the other of type Time. Therefore the Java Connector returns a java.util.Date for the SAP date field containing the date fraction (date at 00:00:00,000) and another java.util.Date for the time field containing the time fraction (i.e. Jan. 1st, 1970 plus time). The utility method joins those two dates into one.
To configure Hibersap, we need to specify some information for the Hibersap framework, plus properties for the Java Connector. To accomplish this, we create an XML file named hibersap.xml in $project_home/src/main/resources/META-INF. Hibersap will look for this file in the classpath under “/META-INF/hibersap.xml”.
In the example we use a minimal set of JCo properties to be able to connect to the back-end SAP system. All valid JCo properties are specified in the JCo library interface com.sap.conn. jco.ext.DestinationDataProvider (see javadoc provided with JCo).
Hibersap’s API is quite similar to Hibernate. There is the notion of a SessionManager which should be created only once in an application, because it is rather expensive to create. One SessionManager is needed for each SAP system which is used by the application.
The SessionManager is responsible for creating Sessions. A Session represents a connection to the SAP system. The first time we call a function module on a Session, Hibersap gets a connection from the underlying connection pool. When closing a session, the connection is returned to the pool. Therefore you have to take care always to close the session, preferably in a finally block, else the connection pool may get exhausted sooner or later.
The following function configures a Hibersap SessionManager. First, an instance of type AnnotationConfiguration has to be created for the named SessionManager, as specified in hibersap.xml. Finally, we build the SessionManager. In a real application this should be done once, reusing the SessionManager throughout the application’s lifetime.
Now it is time to call the function module in SAP. After creating the SessionManager and opening a new Session, we create an instance of our BAPI Class, passing all parameters needed to execute the function as constructor arguments. Then we simply call the execute() method on the Session, passing the BAPI class, which actually performs the call to SAP. Now the flightListBapi object is enriched with all the values returned by the function module and which we have mapped to Java fields in our BAPI Class.
To see the result of the function call, we simply print the BAPI class’ fields to the console in the showResult() method:
Finally, create a main method that calls the showFlightList() method. Build the project with maven on the command-line using “mvn compile” and run the main class, or run it directly from your IDE.
In the example, we are looking for all flights from Frankfurt to Berlin. The result should look like follows, in this example, there were two flights found.
If there were no flights found, the return field will contain the following data returned by SAP:
To see further examples, you may check out the complete hibersap project from the subversion source code repository. See the information provided at the Hibersap project site http://hibersap.org. There you will also find examples of using Hibersap in a Java EE application server with a JCA resource adapter.