Chapter 290. SAP Component The SAP component is a package consisting of a suite of ten different SAP components. There are remote function call (RFC) components that support the sRFC, tRFC, and qRFC protocols; and there are IDoc components that facilitate communication using messages in IDoc format. The component uses the SAP Java Connector (SAP JCo) library to facilitate bidirectional communication with SAP and the SAP IDoc library to facilitate the transmission of documents in the Intermediate Document (IDoc) format. 290.1. Overview Dependencies Maven users need to add the following dependency to their pom.xml file to use this component: <dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap</artifactId> <version>x.x.x</version> <dependency> Additional platform restrictions for the SAP component Because the SAP component depends on the third-party JCo 3 and IDoc 3 libraries, it can only be installed on the platforms that these libraries support. For more details about the supported library versions and platform restrictions, see Red Hat JBoss Fuse Supported Configurations . SAP JCo and SAP IDoc libraries A prerequisite for using the SAP component is that the SAP Java Connector (SAP JCo) libraries and the SAP IDoc library are installed into the lib/ directory of the Java runtime. You can download the appropriate set of SAP libraries for your target operating system from the SAP Service Marketplace. Note You must have an SAP Service Marketplace Account to download and use these libraries. The names of the library files vary depending on the target operating system, as shown in Table 290.1, "Required SAP Libraries" . Table 290.1. Required SAP Libraries SAP Component Linux and UNIX Windows SAP JCo 3 sapjco3.jar libsapjco3.so sapjco3.jar sapjco3.dll SAP IDoc sapidoc3.jar sapidoc3.jar For more information, see the SAP Java Connector documentation. 290.2. Installing required SAP Libraries 290.2.1. Deploying in a Fuse OSGi Container You can install the SAP JCo libraries and the SAP IDoc library into the JBoss Fuse OSGi container as follows: Download the SAP JCo libraries and the SAP IDoc library from the SAP Service Marketplace ( http://service.sap.com/public/connectors ), making sure to choose the appropriate version of the libraries for your operating system. Note You must have an SAP Service Marketplace Account to download and use these libraries. Copy the sapjco3.jar , libsapjco3.so (or sapjco3.dll on Windows), and sapidoc3.jar library files into the lib/ directory of your Fuse installation. Open both the configuration properties file, etc/config.properties , and the custom properties file, etc/custom.properties , in a text editor. In the etc/config.properties file, look for the org.osgi.framework.system.packages.extra property and copy the complete property setting (this setting extends over multiple lines, with a backslash character, \ , used to indicate line continuation). Now paste this setting into the etc/custom.properties file. You can now add the extra packages required to support the SAP libraries. In the etc/custom.properties file, add the required packages to the org.osgi.framework.system.packages.extra setting as shown: Don't forget to include a comma and a backslash, , \ , at the end of each line preceding the new entries, so that the list is properly continued. Restart the container for these changes to take effect. Install the camel-sap feature in the container. In the Karaf console, enter the following command: 290.2.2. Deploying in a JBoss EAP container To deploy the SAP component in a JBoss EAP container, perform the following steps: Download the SAP JCo libraries and the SAP IDoc library from the SAP Service Marketplace ( http://service.sap.com/public/connectors ), making sure to choose the appropriate version of the libraries for your operating system. Note You must have an SAP Service Marketplace Account to download and use these libraries. Copy the JCo library files and the IDoc library file into a subdirectory for your JBoss EAP installation. Important Follow the naming convention The native libraries must be installed in a subdirectory that follows the naming standard, in the form of <osname>-<cpuname> . Information and a complete list of allowed names is available in the JBoss Modules manual . For example, if your host platform is 64-bit Linux ( linux-x86_64 ), install the library files as follows: Example Create a new file called USDJBOSS_HOME/modules/system/layers/fuse/org/wildfly/camel/extras/main/module.xml and add the following content: 290.2.3. Deploying in Spring Boot and OpenShift Container Platform To deploy SAP in your project with Maven using maven-resources and maven-jar plugins, follow these steps: Download the libraries Add dependencies Place libraries in the project Add configuration for the libraries Deploy to OpenShift 290.2.3.1. Downloading libraries You need three libraries: Common library for all environments: sapidoc3.jar Libraries for your architecture: sapjco3.jar sapjco3.so For more information, see the SAP Java Connector documentation. Download the SAP JCo libraries and the SAP IDoc library from the SAP Service Marketplace ( http://service.sap.com/public/connectors ), making sure to choose the appropriate version of the libraries for your operating system. Note You must have an SAP Service Marketplace Account to download and use these libraries. 290.2.3.2. Adding dependencies Maven users need to add the following dependency to their pom.xml file to use this component: <dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap-starter</artifactId> <exclusions> <exclusion> <groupId>com.sap.conn.idoc</groupId> <artifactId>sapidoc3</artifactId> </exclusion> <exclusion> <groupId>com.sap.conn.jco</groupId> <artifactId>sapjco3</artifactId> </exclusion> </exclusions> </dependency> 290.2.3.3. Placing libraries Copy the SAP library files to the lib directory relative to the pom.xml When you run Maven, it follows the instructions in the pom.xml and copy the files to the specified locations. Example: AMD64 Warning Do not add the SAP library files to a custom Maven repository The SAP Java Connector performs validation on the names of the JAR files sapjco3.jar and sapidoc3.jar . If you copy a JAR file to your Maven repository, spring-boot-maven-plugin renames them by appending the version number. This causes validation to fail, preventing the application from deploying properly. 290.2.3.4. Configuring plugins Add the maven configuration to the pom.xml , below the spring-boot-maven-plugin : Add the maven-jar-plugin and set the Class-Path entry to the lib folder location: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <Class-Path>lib/USD{os.arch}/sapjco3.jar lib/USD{os.arch}/sapidoc3.jar</Class-Path> </manifestEntries> </archive> </configuration> </plugin> This creates the correct structure for the necessary artifacts, and make the SAP libraries deploy to the required target directories. Use the maven-resources-plugin in the pom.xml to copy library <plugin> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-resources01</id> <phase>process-classes</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>USD{basedir}/target/lib</outputDirectory> <encoding>UTF-8</encoding> <resources> <resource> <directory>USD{basedir}/lib</directory> <includes> <include>**/**</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin> This copies the libraries directory from the relative lib to target/lib when you run the `oc command. 290.2.3.5. Deploying to Openshift Complete the following steps to deploy to OpenShift, and trigger a Maven build. Run oc to create and configure the build: oc new-build --binary=true --image-stream="<current_Fuse_Java_OpenShift_Imagestream_version>" --name=<application_name> -e "ARTIFACT_COPY_ARGS=-a ." -e "MAVEN_ARGS_APPEND=<additional_args> -e "ARTIFACT_DIR=<relative_path_of_target_directory>" Replace values as needed: <current_Fuse_Java_OpenShift_Imagestream_version> : The current image stream. <application_name> : Application name of your choice. <additional_args> : arguments to append to maven. <relative_path_of_target_directory> : relative path of app to target. Example In this example MAVEN_ARGS_APPEND is used to specify to only build a specific project in the spring-boot directory: Start the build (from the multimodule parent directory) This sends sources from the local host to OpenShift, where the maven build runs. Start the app Example 290.2.4. Deploying in Spring Boot and OpenShift Container Platform using JKube To deploy SAP in your project with JKube using the openshift-maven-plugin plugin, follow these steps: Place the connectors in the lib directory of your project: Example: AMD64 Warning Do not add the SAP library files to a custom Maven repository The SAP Java Connector performs validation on the names of the JAR files sapjco3.jar and sapidoc3.jar . If you copy a JAR file to your Maven repository, spring-boot-maven-plugin renames them by appending the version number. This causes validation to fail, preventing the application from deploying properly. Exclude the embedded connectors from the starter in pom.xml : <dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap-starter</artifactId> <exclusions> <exclusion> <groupId>com.sap.conn.idoc</groupId> <artifactId>sapidoc3</artifactId> </exclusion> <exclusion> <groupId>com.sap.conn.jco</groupId> <artifactId>sapjco3</artifactId> </exclusion> </exclusions> </dependency> Define local connectors as static resources in pom.xml : <resources> <resource> <directory>src/lib/USD{os.arch}/com/sap/conn/idoc</directory> <targetPath>BOOT-INF/lib</targetPath> <includes> <include>*.jar</include> </includes> </resource> <resource> <directory>src/lib/USD{os.arch}/com/sap/conn/jco</directory> <targetPath>BOOT-INF/lib</targetPath> <includes> <include>*.jar</include> </includes> </resource> </resources> Configure resources and deployment configuration, specifying the connector path in pom.xml : <plugin> <groupId>org.eclipse.jkube</groupId> <artifactId>openshift-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <images> <image> <name>USD{project.artifactId}:USD{project.version}</name> <build> <from>USD{java.docker.image}</from> <assembly> <targetDir>/deployments</targetDir> <layers> <layer> <id>static-files</id> <fileSets> <fileSet> <directory>src/lib/USD{os.arch}/com/sap/conn/jco</directory> <outputDirectory>static</outputDirectory> <includes> <include>*.so</include> </includes> </fileSet> </fileSets> </layer> </layers> </assembly> </build> </image> </images> </configuration> <executions> <execution> <goals> <goal>resource</goal> <goal>build</goal> <goal>apply</goal> </goals> </execution> </executions> </plugin> 290.2.4.1. Deploying on Openshift Once the openshift-maven-plugin is configured in pom.xml , you can import the fuse spring-boot image into a specific namespace as a builder image for our application. Start in your application path: Create the project streams: Import the image streams: Create your project Deploy the application with maven: 290.3. URI format There are two different kinds of endpoint provided by the SAP component: the Remote Function Call (RFC) endpoints, and the Intermediate Document (IDoc) endpoints. The URI formats for the RFC endpoints are as follows: The URI formats for the IDoc endpoints are as follows: The URI formats prefixed by sap- endpointKind -destination define destination endpoints (in other words, Camel producer endpoints), and destinationName is the name of a specific outbound connection to a SAP instance. Outbound connections are named and configured at the component level, as described in Section 290.6.2, "Destination Configuration" . The URI formats prefixed by sap- endpointKind -server define server endpoints (in other words, Camel consumer endpoints) and serverName is the name of a specific inbound connection from a SAP instance. Inbound connections are named and configured at the component level, as described in Section 290.6.3, "Server Configuration" . The other components of an RFC endpoint URI are as follows: rfcName (Required) In a destination endpoint URI, the name of the RFC invoked by the endpoint in the connected SAP instance. In a server endpoint URI, the name of the RFC handled by the endpoint when invoked from the connected SAP instance. queueName Specifies the queue this endpoint sends a SAP request to. The other components of an IDoc endpoint URI are as follows: idocType (Required) Specifies the Basic IDoc Type of an IDoc produced by this endpoint. idocTypeExtension Specifies the IDoc Type Extension, if any, of an IDoc produced by this endpoint. systemRelease Specifies the associated SAP Basis Release, if any, of an IDoc produced by this endpoint. applicationRelease Specifes the associated Application Release, if any, of an IDoc produced by this endpoint. queueName Specifies the queue this endpoint sends a SAP request to. 290.4. Options 290.4.1. Options for RFC destination endpoints The RFC destination endpoints ( sap-srfc-destination , sap-trfc-destination , and sap-qrfc-destination ) support the following URI options: Name Default Description stateful false If true , specifies that this endpoint initiates a SAP stateful session transacted false If true , specifies that this endpoint initiates a SAP transaction Options for RFC server endpoints The SAP RFC server endpoints ( sap-srfc-server and sap-trfc-server ) support the following URI options: Name Default Description stateful false If true , specifies that this endpoint initiates a SAP stateful session. propagateExceptions false (sap-trfc-server endpoint only) If true , specifies that this endpoint propagates exceptions back to the caller in SAP, instead of the exchange's exception handler Options for the IDoc List Server endpoint The SAP IDoc List Server endpoint ( sap-idoclist-server ) supports the following URI options: Name Default Description stateful false If true , specifies that this endpoint initiates a SAP stateful session. propagateExceptions false If true , specifies that this endpoint propagates exceptions back to the caller in SAP, instead of the exchange's exception handler 290.5. Summary of the RFC and IDoc endpoints The SAP component package provides the following RFC and IDoc endpoints: sap-srfc-destination JBoss Fuse SAP Synchronous Remote Function Call Destination Camel component. Use this endpoint in cases where Camel routes require synchronous delivery of requests to and responses from a SAP system. Note The sRFC protocol used by this component delivers requests and responses to and from a SAP system with best effort . In case of a communication error while sending a request, the completion status of a remote function call in the receiving SAP system remains in doubt . sap-trfc-destination JBoss Fuse SAP Transactional Remote Function Call Destination Camel component. Use this endpoint in cases where requests must be delivered to the receiving SAP system at most once . To accomplish this, the component generates a transaction ID, tid , which accompanies every request sent through the component in a route's exchange. The receiving SAP system records the tid accompanying a request before delivering the request; if the SAP system receives the request again with the same tid it does not deliver the request. Thus, if a route encounters a communication error when sending a request through an endpoint of this component, it can retry sending the request within the same exchange knowing it is delivered and executed only once. Note The tRFC protocol used by this component is asynchronous and does not return a response. Thus the endpoints of this component do not return a response message. Note This component does not guarantee the order of a series of requests through its endpoints, and the delivery and execution order of these requests may differ on the receiving SAP system due to communication errors and resends of a request. For guaranteed delivery order, please see the JBoss Fuse SAP Queued Remote Function Call Destination Camel component. sap-qrfc-destination JBoss Fuse SAP Queued Remote Function Call Destination Camel component. This component extends the capabilities of the JBoss Fuse Transactional Remote Function Call Destination camel component by adding in order delivery guarantees to the delivery of requests through its endpoints. Use this endpoint in cases where a series of requests depend on each other and must be delivered to the receiving SAP system at most once and in order . The component accomplishes the at most once delivery guarantees using the same mechanisms as the JBoss Fuse SAP Transactional Remote Function Call Destination Camel component. The ordering guarantee is accomplished by serializing the requests in the order they are received by the SAP system to an inbound queue . Inbound queues are processed by the QIN scheduler within SAP. When the inbound queue is activated , the QIN Scheduler executes the queue requests in order. Note The qRFC protocol used by this component is asynchronous and does not return a response. Thus the endpoints of this component do not return a response message. sap-srfc-server JBoss Fuse SAP Synchronous Remote Function Call Server Camel component. Use this component and its endpoints in cases where a Camel route is required to synchronously handle requests from and responses to a SAP system. sap-trfc-server JBoss Fuse SAP Transactional Remote Function Call Server Camel component. Use this endpoint in cases where the sending SAP system requires at most once delivery of its requests to a Camel route. To accomplish this, the sending SAP system generates a transaction ID, tid , which accompanies every request it sends to the component's endpoints. The sending SAP system first checks with the component whether a given tid has been received by it before sending a series of requests associated with the tid . The component checks the list of received tid s it maintains, record the sent tid if it is not in that list, and then respond to the sending SAP system, indicating whether the tid had already been recorded. If the tid has not been previously recorded, the sending SAP system transmits the series of requests. This enables a sending SAP system to reliably send a series of requests once to a camel route. sap-idoc-destination JBoss Fuse SAP IDoc Destination Camel component. Use this endpoint in cases where a Camel route is required to send a list of Intermediate Documents (IDocs) to a SAP system. sap-idoclist-destination JBoss Fuse SAP IDoc List Destination Camel component. Use this endpoint in cases where a Camel route is required to send a list of Intermediate documents (IDocs) to a SAP system. sap-qidoc-destination JBoss Fuse SAP Queued IDoc Destination Camel component. Use this component and its endpoints in cases where a Camel route is required to send a list of Intermediate documents (IDocs) to a SAP system in order . sap-qidoclist-destination JBoss Fuse SAP Queued IDoc List Destination Camel component. Use this component and its endpoints in cases where a camel route is required to send a list of Intermediate documents (IDocs) to a SAP system in order . sap-idoclist-server JBoss Fuse SAP IDoc List Server Camel component. Use this endpoint in cases where a sending SAP system requires delivery of Intermediate Document lists to a Camel route. This component uses the tRFC protocol to communicate with SAP as described in the sap-trfc-server-standalone quick start. SAP RFC destination endpoint An RFC destination endpoint supports outbound communication to SAP, which enable these endpoints to make RFC calls out to ABAP function modules in SAP. An RFC destination endpoint is configured to make an RFC call to a specific ABAP function over a specific connection to a SAP instance. An RFC destination is a logical designation for an outbound connection and has a unique name. An RFC destination is specified by a set of connection parameters called destination data . An RFC destination endpoint extracts an RFC request from the input message of the IN-OUT exchanges it receives and dispatch that request in a function call to SAP. The output message of the exchange contains the response from the function call. Since SAP RFC destination endpoints only support outbound communication, an RFC destination endpoint only supports the creation of producers. SAP RFC server endpoint An RFC server endpoint supports inbound communication from SAP, which enables ABAP applications in SAP to make RFC calls into server endpoints. An ABAP application interacts with an RFC server endpoint as if it were a remote function module. An RFC server endpoint is configured to receive an RFC call to a specific RFC function over a specific connection from a SAP instance. An RFC server is a logical designation for an inbound connection and has a unique name. An RFC server is specified by a set of connection parameters called server data . An RFC server endpoint handles an incoming RFC request and dispatch it as the input message of an IN-OUT exchange. The output message of the exchange is returned as the response of the RFC call. Since SAP RFC server endpoints only support inbound communication, an RFC server endpoint only supports the creation of consumers. SAP IDoc and IDoc list destination endpoints An IDoc destination endpoint supports outbound communication to SAP, which can then perform further processing on the IDoc message. An IDoc document represents a business transaction, which can easily be exchanged with non-SAP systems. An IDoc destination is specified by a set of connection parameters called destination data . An IDoc list destination endpoint is similar to an IDoc destination endpoint, except that the messages it handles consist of a list of IDoc documents. SAP IDoc list server endpoint An IDoc list server endpoint supports inbound communication from SAP, enabling a Camel route to receive a list of IDoc documents from a SAP system. An IDoc list server is specified by a set of connection parameters called server data . metadata repositories A metadata repository is used to store the following kinds of metadata: Interface descriptions of function modules This metadata is used by the JCo and ABAP runtimes to check RFC calls to ensure the type-safe transfer of data between communication partners before dispatching those calls. A repository is populated with repository data. Repository data is a map of named function templates. A function template contains the metadata describing all the parameters and their typing information passed to and from a function module and has the unique name of the function module it describes. IDoc type descriptions This metadata is used by the IDoc runtime to ensure that the IDoc documents are correctly formatted before being sent to a communication partner. A basic IDoc type consists of a name, a list of permitted segments, and a description of the hierarchical relationship between the segments. Some additional constraints can be imposed on the segments: a segment can be mandatory or optional; and it is possible to specify a minimum/maximum range for each segment (defining the number of allowed repetitions of that segment). SAP destination and server endpoints thus require access to a repository to send and receive RFC calls and to send and receive IDoc documents. For RFC calls, the metadata for all function modules invoked and handled by the endpoints must reside within the repository; and for IDoc endpoints, the metadata for all IDoc types and IDoc type extensions handled by the endpoints must reside within the repository. The location of the repository used by a destination and server endpoint is specified in the destination data and the server data of their respective connections. In the case of a SAP destination endpoint, the repository it uses typically resides in a SAP system and it defaults to the SAP system it is connected to. This default requires no explicit configuration in the destination data. Furthermore, the metadata for the remote function call that a destination endpoint makes already exist in a repository for any existing function module that it calls. The metadata for calls made by destination endpoints thus require no configuration in the SAP component. On the other hand, the metadata for function calls handled by server endpoints do not typically reside in the repository of a SAP system and must instead be provided by a repository residing in the SAP component. The SAP component maintains a map of named metadata repositories. The name of a repository corresponds to the name of the server to which it provides metadata. 290.6. Configuration The SAP component maintains three maps to store destination data, server data , and repository data. The destination data store and the server data store use a special configuration object, SapConnectionConfiguration , which automatically gets injected into the SAP component (in the context of Blueprint XML configuration or Spring XML configuration files). The repository data store must be configured directly on the relevant SAP component. 290.6.1. Configuration Overview Overview The SAP component maintains three maps to store destination data, server data , and repository data. The component's property, destinationDataStore , stores destination data keyed by destination name. The property, serverDataStore , stores server data keyed by server name. The property, repositoryDataStore , stores repository data keyed by repository name. You must pass these configurations to the component during its initialization. Example The following example shows how to configure a sample destination data store and a sample server data store in a Blueprint XML file. The sap-configuration bean (of type SapConnectionConfiguration ) is automatically injected into any SAP component used in this XML file. <?xml version="1.0" encoding="UTF-8"?> <blueprint ... > ... <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> <property name="serverDataStore"> <map> <entry key="quickstartServer" value-ref="quickstartServerData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="passowrd" /> <property name="lang" value="en" /> </bean> <!-- Configures an Inbound SAP Connection --> <!-- *** Please enter the connection property values for your environment ** --> <bean id="quickstartServerData" class="org.fusesource.camel.component.sap.model.rfc.impl.ServerDataImpl"> <property name="gwhost" value="example.com" /> <property name="gwserv" value="3300" /> <!-- Do not change the following property values --> <property name="progid" value="QUICKSTART" /> <property name="repositoryDestination" value="quickstartDest" /> <property name="connectionCount" value="2" /> </bean> </blueprint> 290.6.2. Destination Configuration Overview The configurations for destinations are maintained in the destinationDataStore property of the SAP component. Each entry in this map configures a distinct outbound connection to an SAP instance. The key for each entry is the name of the outbound connection and is used in the destinationName component of a destination endpoint URI as described in the URI format section. The value for each entry is a destination data configuration object - org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl - that specifies the configuration of an outbound SAP connection. Sample destination configuration The following Blueprint XML code shows how to configure a sample destination with the name quickstartDest . <?xml version="1.0" encoding="UTF-8"?> <blueprint ... > ... <!-- Create interceptor to support tRFC processing --> <bean id="currentProcessorDefinitionInterceptor" class="org.fusesource.camel.component.sap.CurrentProcessorDefinitionInterceptStrategy" /> <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="password" /> <property name="lang" value="en" /> </bean> </blueprint> For example, after configuring the destination as shown in the preceding Blueprint XML file, you could invoke the BAPI_FLCUST_GETLIST remote function call on the quickstartDest destination using the following URI: sap-srfc-destination:quickstartDest:BAPI_FLCUST_GETLIST Interceptor for tRFC and qRFC destinations The preceding sample destination configuration shows the instantiation of a CurrentProcessorDefinitionInterceptStrategy object. This object installs an interceptor in the Camel runtime, enabling the Camel SAP component to keep track of its position within a Camel route while handling RFC transactions. For more details, see the section called "Transactional RFC destination endpoints" . Important This interceptor must be installed in the Camel runtime to properly manage outbound transactional RFC communication. It is critically important for transactional RFC destination endpoints (such as sap-trfc-destination and sap-qrfc-destination ). The Destination RFC Transaction Handlers issue warnings into the Camel log if the strategy is not found at runtime, and in this situation the Camel runtime must to be re-provisioned and restarted to properly manage outbound transactional RFC communication. Log-in and authentication options The following table lists the log-in and authentication options for configuring a destination in the SAP destination data store: Name Default Value Description client SAP client, mandatory log-in parameter user Log-in user, log-in parameter for password based authentication aliasUser Log-in user alias, can be used instead of log-in user userId User identity to use for log-in to the ABAP AS. Used by the JCo runtime, if the destination configuration uses SSO/assertion ticket, certificate, current user, or SNC environment for authentication. If there is no user or user alias, the user ID is mandatory. This ID is not used by the SAP backend, the JCo runtime uses it locally. passwd Log-in password, log-in parameter for password-based authentication lang Log-in language to use instead of the user language mysapsso2 Use the specified SAP Cookie Version 2 as a log-in ticket for SSO based authentication x509cert Use the specified X509 certificate for certificate based authentication lcheck Postpone the authentication until the first call - 1 (enable). Use lcheck in special cases only . useSapGui Use a visible, hidden, or do not use SAP GUI codePage Additional log-in parameter to define the codepage that is used to convert the log-in parameters. Use codePage in special cases only. getsso2 Order a SSO ticket after log-in, the obtained ticket is available in the destination attributes denyInitialPassword If set to 1 , using initial passwords leads to an exception (default is 0 ). Connection options The following table lists the connection options for configuring a destination in the SAP destination data store: Name Default Value Description saprouter SAP Router string for connection to systems behind a SAP Router. SAP Router string contains the chain of SAP Routers and its port numbers and has the form: (/H/<host>[/S/<port>])+ sysnr System number of the SAP ABAP application server, mandatory for a direct connection ashost SAP ABAP application server, mandatory for a direct connection mshost SAP message server, mandatory property for a load balancing connection msserv SAP message server port, optional property for a load balancing connection. To resolve the service names sapmsXXX, the network layer of the operating system performs a look-up in etc/services . If using port numbers instead of symbolic service names, there are no look-ups and additional entries are not needed. gwhost Allows specifying a concrete gateway. Use this for establishing the connection to an application server. If not specified the gateway on the application server is used. gwserv Set this when using gwhost . Allows specifying the port used on that gateway. If not specified the port of the gateway on the application server is used. To resolve the service names sapgwXXX, the network layer of the operating system performs a look-up in etc/services . If using port numbers instead of symbolic service names, there are no look-ups and additional entries are not needed. r3name System ID of the SAP system, mandatory property for a load balancing connection. group Group of SAP application servers, mandatory property for a load balancing connection network LAN Set this value depending on the network quality between JCo and your target system to optimize performance. The valid values are LAN or WAN (which is relevant for fast serialization only). WAN uses a slower but more efficient compression algorithm, with data analysis for further compression options. LAN uses a very fast compression algorithm, with only basic data analysis. With the LAN option, the compression ratio is not as efficient but the network transfer time is considered to be less significant. The default setting is LAN . serializationFormat rowBased Format for serialization. Can be rowBased (default) or columnBased (fast serialization). Connection pool options The following table lists the connection pool options for configuring a destination in the SAP destination data store: Name Default Value Description peakLimit 0 The maximum number of simultaneously active outbound connections for a destination. A value of 0 allows an unlimited number of active connections. Otherwise, it is automatically increased to poolCapacity . Default setting is the value of poolCapacity if configured. If poolCapacity is not specified, the default is 0 (unlimited). poolCapacity 1 The maximum number of idle outbound connections kept open by the destination. A value of 0 means no connection pooling (default is 1 ). expirationTime The minimum time in milliseconds a free connection held internally by the destination must be kept open. expirationPeriod The period in milliseconds after which the destination checks expiration for the released connections. maxGetTime The maximum time in milliseconds to wait for a connection, if the maximum allowed number of connections has already been allocated by the application. Secure network connection options The following table lists the secure network options for configuring a destination in the SAP destination data store: Name Default Value Description sncMode Secure network connection (SNC) mode, 0 (off) or 1 (on) sncPartnername SNC partner, for example: p:CN=R3, O=XYZ-INC, C=EN sncQop SNC level of security: 1 to 9 sncMyname Own SNC name. Overrides environment settings sncLibrary Path to library that provides SNC service Repository options The following table lists the repository options for configuring a destination in the SAP destination data store: Name Default Value Description repositoryDest Specifies which destination to use as repository. repositoryUser This defines the user for repository calls, if a repository destination has not been defined. This enables you to use a different user for repository look-ups. repositoryPasswd The password for a repository user. Mandatory when using a repository user. repositorySnc (Optional) If SNC is used for this destination, it is possible to turn it off for repository connections, if this property is set to 0 . Default setting is the value of jco.client.snc_mode . For special cases only. repositoryRoundtripOptimization Enable the RFC_METADATA_GET API, which provides repository data in one round trip. 1 Activates use of RFC_METADATA_GET in ABAP System, 0 Deactivates RFC_METADATA_GET in ABAP System. If the property is not set, the destination initially does a remote call to check whether RFC_METADATA_GET is available. If it is available, the destination uses it. Note If the repository is already initialized (for example because it is used by some other destination) this property does not have any effect. Generally, this property is related to the ABAP System, and should have the same value on all destinations pointing to the same ABAP System. See note 1456826 for backend prerequisites. Trace configuration options The following table lists the trace configuration options for configuring a destination in the SAP destination data store: Name Default Value Description trace Enable/disable RFC trace ( 0 or 1 ) cpicTrace Enable/disable CPIC trace [0..3] 290.6.3. Server Configuration Overview The configurations for servers are maintained in the serverDataStore property of the SAP component. Each entry in this map configures a distinct inbound connection from an SAP instance. The key for each entry is the name of the outbound connection and is used in the serverName component of a server endpoint URI as described in the URI format section. The value for each entry is a server data configuration object , org.fusesource.camel.component.sap.model.rfc.impl.ServerDataImpl , that defines the configuration of an inbound SAP connection. Sample server configuration The following Blueprint XML code shows how to create a sample server configuration with the name, quickstartServer . <?xml version="1.0" encoding="UTF-8"?> <blueprint ... > ... <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> <property name="serverDataStore"> <map> <entry key="quickstartServer" value-ref="quickstartServerData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="passowrd" /> <property name="lang" value="en" /> </bean> <!-- Configures an Inbound SAP Connection --> <!-- *** Please enter the connection property values for your environment ** --> <bean id="quickstartServerData" class="org.fusesource.camel.component.sap.model.rfc.impl.ServerDataImpl"> <property name="gwhost" value="example.com" /> <property name="gwserv" value="3300" /> <!-- Do not change the following property values --> <property name="progid" value="QUICKSTART" /> <property name="repositoryDestination" value="quickstartDest" /> <property name="connectionCount" value="2" /> </bean> </blueprint> Notice how this example also configures a destination connection, quickstartDest , which the server uses to retrieve metadata from a remote SAP instance. This destination is configured in the server data through the repositoryDestination option. If you do not configure this option, you would need to create a local metadata repository instead (see Section 290.6.4, "Repository Configuration" ). For example, after configuring the destination as shown in the preceding Blueprint XML file, you could handle the BAPI_FLCUST_GETLIST remote function call from an invoking client, using the following URI: sap-srfc-server:quickstartServer:BAPI_FLCUST_GETLIST Required options The required options for the server data configuration object are, as follows: Name Default Value Description gwhost Gateway host to register the server connection with. gwserv Gateway service, which is the port on which a registration can be done. To resolve the service names sapgwXXX , the network layer of the operating system performs a look-up in etc/services . If using port numbers instead of symbolic service names, there are no look-ups and additional entries are not needed. progid The program ID with which the registration is done. Serves as identifier on the gateway and in the destination in the ABAP system. repositoryDestination Specifies a destination name that the server can use to retrieve metadata from a metadata repository hosted in a remote SAP server. connectionCount The number of connections to register with the gateway. Secure network connection options The secure network connection options for the server data configuration object are, as follows: Name Default Value Description sncMode Secure network connection (SNC) mode, 0 (off) or 1 (on) sncQop SNC level of security, 1 to 9 sncMyname SNC name of your server. Overrides the default SNC name. Typically something like p:CN=JCoServer, O=ACompany, C=EN . sncLib Path to library which provides SNC service. If this property is not provided, the value of the jco.middleware.snc_lib property is used instead Other options The other options for the server data configuration object are, as follows: Name Default Value Description saprouter SAP router string to use for a system protected by a firewall, which can therefore only be reached through a SAProuter, when registering the server at the gateway of that ABAP System. A typical router string is /H/firewall.hostname/H/ maxStartupDelay The maximum time (in seconds) between two start-up attempts in case of failures. Initially, the waiting time is doubled from 1 second after each start-up failure until the maximum value is reached, or the server can be started successfully. trace Enable/disable RFC trace ( 0 or 1 ) workerThreadCount The maximum number of threads used by the server connection. If not set, the value for the connectionCount is used as the workerThreadCount . The maximum number of threads can not exceed 99. workerThreadMinCount The minimum number of threads used by server connection. If not set, the value for connectionCount is used as the workerThreadMinCount . 290.6.4. Repository Configuration Overview The configurations for repositories are maintained in the repositoryDataStore property of the SAP Component. Each entry in this map configures a distinct repository. The key for each entry is the name of the repository and this key also corresponds to the name of server to which this repository is attached. The value of each entry is a repository data configuration object, org.fusesource.camel.component.sap.model.rfc.impl.RepositoryDataImpl , that defines the contents of a metadata repository. A repository data object is a map of function template configuration objects, org.fuesource.camel.component.sap.model.rfc.impl.FunctionTemplateImpl . Each entry in this map specifies the interface of a function module and the key for each entry is the name of the function module specified. Repository data example The following code shows a simple example of configuring a metadata repository: <?xml version="1.0" encoding="UTF-8"?> <blueprint ... > ... <!-- Configures the sap-srfc-server component --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="repositoryDataStore"> <map> <entry key="nplServer" value-ref="nplRepositoryData" /> </map> </property> </bean> <!-- Configures a metadata Repository --> <bean id="nplRepositoryData" class="org.fusesource.camel.component.sap.model.rfc.impl.RepositoryDataImpl"> <property name="functionTemplates"> <map> <entry key="BOOK_FLIGHT" value-ref="bookFlightFunctionTemplate" /> </map> </property> </bean> ... </blueprint> Function template properties The interface of a function module consists of four parameter lists by which data is transferred back and forth to the function module in an RFC call. Each parameter list consists of one or more fields, each of which is a named parameter transferred in an RFC call. The following parameter lists and exception list are supported: The import parameter list contains parameter values that are sent to a function module in an RFC call; The export parameter list contains parameter values that are returned by a function module in an RFC call; The changing parameter list contains parameter values that are sent to and returned by a function module in an RFC call; The table parameter list contains internal table values that are sent to and returned by a function module in an RFC call. The interface of a function module also consists of an exception list of ABAP exceptions that may be raised when the module is invoked in an RFC call. A function template describes the name and type of parameters in each parameter list of a function interface and the ABAP exceptions thrown by the function. A function template object maintains five property lists of metadata objects, as described in the following table. Property Description importParameterList A list of list field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMeataDataImpl . Specifies the parameters that are sent in an RFC call to a function module. changingParameterList A list of list field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMeataDataImpl . Specifies the parameters that sent and returned in an RFC call to and from a function module. exportParameterList A list of list field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMeataDataImpl . Specifies the parameters that are returned in an RFC call from a function module. tableParameterList A list of list field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMeataDataImpl . Specifies the table parameters that are sent and returned in an RFC call to and from a function module. exceptionList A list of ABAP exception metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.AbapExceptionImpl . Specifies the ABAP exceptions potentially raised in an RFC call of function module. Function template example The following example shows an outline of how to configure a function template: List field metadata properties A list field metadata object, org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMeataDataImpl , specifies the name and type of a field in a parameter list. For an elementary parameter field ( CHAR , DATE , BCD , TIME , BYTE , NUM , FLOAT , INT , INT1 , INT2 , DECF16 , DECF34 , STRING , XSTRING ), the following table lists the configuration properties that may be set on a list field metadata object: Name Default Value Description name - The name of the parameter field. type - The parameter type of the field. byteLength - The field length in bytes for a non-Unicode layout. This value depends on the parameter type. See Section 290.9, "Message Body for RFC" . unicodeByteLength - The field length in bytes for a Unicode layout. This value depends on the parameter type. See Section 290.9, "Message Body for RFC" . decimals 0 The number of decimals in field value; only required for parameter types BCD and FLOAT. See Section 290.9, "Message Body for RFC" . optional false If true , the field is optional and need not be set in a RFC call Note All elementary parameter fields require that the name , type , byteLength and unicodeByteLength properties be specified in the field metadata object. In addition, the BCD , FLOAT , DECF16 and DECF34 fields require the decimal property to be specified in the field metadata object. For a complex parameter field of type TABLE or STRUCTURE , the following table lists the configuration properties that may be set on a list field metadata object: Name Default Value Description name - The name of the parameter field type - The parameter type of the field recordMetaData - The metadata for the structure or table. A record metadata object, org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl , is passed to specify the fields in the structure or table rows. optional false If true , the field is optional and need not be set in a RFC call Note All complex parameter fields require that the name , type and recordMetaData properties be specified in the field metadata object. The value of the recordMetaData property is a record field metadata object, org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl , which specifies the structure of a nested structure or the structure of a table row. Elementary list field metadata example The following metadata configuration specifies an optional, 24-digit packed BCD number parameter with two decimal places named TICKET_PRICE : <bean class="org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMetaDataImpl"> <property name="name" value="TICKET_PRICE" /> <property name="type" value="BCD" /> <property name="byteLength" value="12" /> <property name="unicodeByteLength" value="24" /> <property name="decimals" value="2" /> <property name="optional" value="true" /> </bean> Complex list field metadata example The following metadata configuration specifies a required TABLE parameter named CONNINFO with a row structure specified by the connectionInfo record metadata object: Record metadata properties A record metadata object, org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl , specifies the name and contents of a nested STRUCTURE or the row of a TABLE parameter. A record metadata object maintains a list of record field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.FieldMetaDataImpl , which specify the parameters that reside in the nested structure or table row. The following table lists configuration properties that may be set on a record metadata object: Name Default Value Description name - The name of the record. recordFieldMetaData - The list of record field metadata objects, org.fusesource.camel.component.sap.model.rfc.impl.FieldMetaDataImpl . Specifies the fields contained within the structure. Note All properties of the record metadata object are required. Record metadata example The following example shows how to configure a record metadata object: <bean id="connectionInfo" class="org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl"> <property name="name" value="CONNECTION_INFO" /> <property name="recordFieldMetaData"> <list> ... </list> </property> </bean> Record field metadata properties A record field metadata object, org.fusesource.camel.component.sap.model.rfc.impl.FieldMetaDataImpl , specifies the name and type of a parameter field withing a structure. A record field metadata object is similar to a parameter field metadata object, except that the offsets of the individual field locations within the nested structure or table row must be additionally specified. The non-Unicode and Unicode offsets of an individual field must be calculated and specified from the sum of non-Unicode and Unicode byte lengths of the preceding fields in the structure or row. Note Failure to properly specify the offsets of fields in nested structures and table rows causes the field storage of parameters in the underlying JCo and ABAP runtimes to overlap and prevent the proper transfer of values in RFC calls. For an elementary parameter field ( CHAR , DATE , BCD , TIME , BYTE , NUM , FLOAT , INT , INT1 , INT2 , DECF16 , DECF34 , STRING , XSTRING ), the following table lists the configuration properties that may be set on a record field metadata object: Name Default Value Description name - The name of the parameter field type - The parameter type of the field byteLength - The field length in bytes for a non-Unicode layout. This value depends on the parameter type. See Section 290.9, "Message Body for RFC" . unicodeByteLength - The field length in bytes for a Unicode layout. This value depends on the parameter type. See Section 290.9, "Message Body for RFC" . byteOffset - The field offset in bytes for non-Unicode layout. This offset is the byte location of the field within the enclosing structure. unicodeByteOffset - The field offset in bytes for Unicode layout. This offset is the byte location of the field within the enclosing structure. decimals 0 The number of decimals in field value; only required for parameter types BCD and FLOAT . See Section 290.9, "Message Body for RFC" . For a complex parameter field of type TABLE or STRUCTURE , the following table lists the configuration properties that may be set on a record field metadata object: Name Default Value Description name - The name of the parameter field type - The parameter type of the field byteOffset - The field offset in bytes for non-Unicode layout. This offset is the byte location of the field within the enclosing structure. unicodeByteOffset - The field offset in bytes for Unicode layout. This offset is the byte location of the field within the enclosing structure. recordMetaData - The metadata for the structure or table. A record metadata object, org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl , is passed to specify the fields in the structure or table rows. Elementary record field metadata example The following metadata configuration specifies a DATE field parameter named ARRDATE located 85 bytes into the enclosing structure in the case of a non-Unicode layout and located 170 bytes into the enclosing structure in the case of a Unicode layout: Complex record field metadata example The following metadata configuration specifies a STRUCTURE field parameter named FLTINFO with a structure specified by the flightInfo record metadata object. The parameter is located at the beginning of the enclosing structure in both the case of a non-Unicode and Unicode layout. 290.7. Message Headers The SAP component supports the following message headers: Header Description CamelSap.scheme The URI scheme of the last endpoint to process the message. Use one of the following values: sap-srfc-destination sap-trfc-destination sap-qrfc-destination sap-srfc-server sap-trfc-server sap-idoc-destination sap-idoclist-destination sap-qidoc-destination sap-qidoclist-destination sap-idoclist-server CamelSap.destinationName The destination name of the last destination endpoint to process the message. CamelSap.serverName The server name of the last server endpoint to process the message. CamelSap.queueName The queue name of the last queuing endpoint to process the message. CamelSap.rfcName The RFC name of the last RFC endpoint to process the message. CamelSap.idocType The IDoc type of the last IDoc endpoint to process the message. CamelSap.idocTypeExtension The IDoc type extension, if any, of the last IDoc endpoint to process the message. CamelSap.systemRelease The system release, if any, of the last IDoc endpoint to process the message. CamelSap.applicationRelease The application release, if any, of the last IDoc endpoint to process the message. 290.8. Exchange Properties The SAP component adds the following exchange properties: Property Description CamelSap.destinationPropertiesMap A map containing the properties of each SAP destination encountered by the exchange. The map is keyed by destination name and each entry is a java.util.Properties object containing the configuration properties of that destination. CamelSap.serverPropertiesMap A map containing the properties of each SAP server encountered by the exchange. The map is keyed by server name and each entry is a java.util.Properties object containing the configuration properties of that server. 290.9. Message Body for RFC Request and response objects An SAP endpoint expects to receive a message with a message body containing an SAP request object and returns a message with a message body containing an SAP response object. SAP requests and responses are fixed map data structures containing named fields with each field having a predefined data type. Note The named fields in an SAP request and response are specific to an SAP endpoint, with each endpoint defining the parameters in the SAP request and the acceptable response. An SAP endpoint provides factory methods to create the request and response objects that are specific to it. Structure objects Both SAP request and response objects are represented in Java as a structure object which supports the org.fusesource.camel.component.sap.model.rfc.Structure interface. This interface extends both the java.util.Map and org.eclipse.emf.ecore.EObject interfaces. The field values in a structure object are accessed through the field's getter methods in the map interface. In addition, the structure interface provides a type-restricted method to retrieve field values. Structure objects are implemented in the component runtime using the Eclipse Modeling Framework (EMF) and support that framework's EObject interface. Instances of a structure object have attached metadata which define and restrict the structure and contents of the map of fields it provides. This metadata can be accessed and introspected using the standard methods provided by EMF. Please refer to the EMF documentation for further details. Note Attempts to get a parameter not defined on a structure object returns null. Attempts to set a parameter not defined on a structure throws an exception as well as attempts to set the value of a parameter with an incorrect type. As discussed in the following sections, structure objects can contain fields that contain values of the complex field types, STRUCTURE and TABLE . Note It is unnecessary to create instances of these types and add them to the structure. Instances of these field values are created on demand if necessary when accessed in the enclosing structure. Field types The fields that reside within the structure object of an SAP request or response may be either elementary or complex . An elementary field contains a single scalar value, whereas a complex field contains one or more fields of an elementary or complex type. Elementary field types An elementary field may be a character, numeric, hexadecimal or string field type. The following table summarizes the types of elementary fields that may reside in a structure object: Field Type Corresponding Java Type Byte Length Unicode Byte Length Number Decimals Digits Description CHAR java.lang.String 1 to 65535 1 to 65535 - ABAP Type 'C': Fixed sized character string DATE java.util.Date 8 16 - ABAP Type 'D': Date (format: YYYYMMDD) BCD java.math.BigDecimal 1 to 16 1 to 16 0 to 14 ABAP Type 'P': Packed BCD number. A BCD number contains two digits per byte. TIME java.util.Date 6 12 - ABAP Type 'T': Time (format: HHMMSS) BYTE byte[] 1 to 65535 1 to 65535 - ABAP Type 'X':Fixed sized byte array NUM java.lang.String 1 to 65535 1 to 65535 - ABAP Type 'N': Fixed sized numeric character string FLOAT java.lang.Double 8 8 0 to 15 ABAP Type 'F': Floating point number INT java.lang.Integer 4 4 - ABAP Type 'I': 4-byte Integer INT2 java.lang.Integer 2 2 - ABAP Type 'S': 2-byte Integer INT1 java.lang.Integer 1 1 - ABAP Type 'B': 1-byte Integer DECF16 java.match.BigDecimal 8 8 16 ABAP Type 'decfloat16': 8 -byte Decimal Floating Point Number DECF34 java.math.BigDecimal 16 16 34 ABAP Type 'decfloat34': 16-byte Decimal Floating Point Number STRING java.lang.String 8 8 - ABAP Type 'G': Variable length character string XSTRING byte[] 8 8 - ABAP Type 'Y': Variable length byte array Character field types A character field contains a fixed sized character string that may use either a non-Unicode or Unicode character encoding in the underlying JCo and ABAP runtimes. Non-Unicode character strings encode one character per byte. Unicode characters strings are encoded in two bytes using UTF-16 encoding. Character field values are represented in Java as java.lang.String objects and the underlying JCo runtime is responsible for the conversion to their ABAP representation. A character field declares its field length in its associated byteLength and unicodeByteLength properties, which determine the length of the field's character string in each encoding system. CHAR A CHAR character field is a text field containing alphanumeric characters and corresponds to the ABAP type C. NUM A NUM character field is a numeric text field containing numeric characters only and corresponds to the ABAP type N. DATE A DATE character field is an 8 character date field with the year, month and day formatted as YYYYMMDD and corresponds to the ABAP type D. TIME A TIME character field is a 6 character time field with the hours, minutes and seconds formatted as HHMMSS and corresponds to the ABAP type T. Numeric field types A numeric field contains a number. The following numeric field types are supported: INT An INT numeric field is an integer field stored as a 4-byte integer value in the underlying JCo and ABAP runtimes and corresponds to the ABAP type I. An INT field value is represented in Java as a java.lang.Integer object. INT2 An INT2 numeric field is an integer field stored as a 2-byte integer value in the underlying JCo and ABAP runtimes and corresponds to the ABAP type S. An INT2 field value is represented in Java as a java.lang.Integer object. INT1 An INT1 field is an integer field stored as a 1-byte integer value in the underlying JCo and ABAP runtimes value and corresponds to the ABAP type B. An INT1 field value is represented in Java as a java.lang.Integer object. FLOAT A FLOAT field is a binary floating point number field stored as an 8-byte double value in the underlying JCo and ABAP runtimes and corresponds to the ABAP type F. A FLOAT field declares the number of decimal digits that the field's value contains in its associated decimal property. In the case of a FLOAT field, this decimal property can have a value between 1 and 15 digits. A FLOAT field value is represented in Java as a java.lang.Double object. BCD A BCD field is a binary coded decimal field stored as a 1 to 16 byte packed number in the underlying JCo and ABAP runtimes and corresponds to the ABAP type P. A packed number stores two decimal digits per byte. A BCD field declares its field length in its associated byteLength and unicodeByteLength properties. In the case of a BCD field, these properties can have a value between 1 and 16 bytes and both properties have the same value. A BCD field declares the number of decimal digits that the field's value contains in its associated decimal property. In the case of a BCD field, this decimal property can have a value between 1 and 14 digits. A BCD field value is represented in Java as a java.math.BigDecimal . DECF16 A DECF16 field is a decimal floating point stored as an 8-byte IEEE 754 decimal64 floating point value in the underlying JCo and ABAP runtimes and corresponds to the ABAP type decfloat16 . The value of a DECF16 field has 16 decimal digits. The value of a DECF16 field is represented in Java as java.math.BigDecimal . DECF34 A DECF34 field is a decimal floating point stored as a 16-byte IEEE 754 decimal128 floating point value in the underlying JCo and ABAP runtimes and corresponds to the ABAP type decfloat34 . The value of a DECF34 field has 34 decimal digits. The value of a DECF34 field is represented in Java as java.math.BigDecimal . Hexadecimal field types A hexadecimal field contains raw binary data. The following hexadecimal field types are supported: BYTE A BYTE field is a fixed sized byte string stored as a byte array in the underlying JCo and ABAP runtimes and corresponds to the ABAP type X. A BYTE field declares its field length in its associated byteLength and unicodeByteLength properties. In the case of a BYTE field, these properties can have a value between 1 and 65535 bytes and both properties have the same value. The value of a BYTE field is represented in Java as a byte[] object. String field types A string field references a variable length string value. The length of that string value is not fixed until runtime. The storage for the string value is dynamically created in the underlying JCo and ABAP runtimes. The storage for the string field itself is fixed and contains only a string header. STRING A STRING field refers to a character string and is stored in the underlying JCo and ABAP runtimes as an 8-byte value. It corresponds to the ABAP type G. The value of the STRING field is represented in Java as a java.lang.String object. XSTRING An XSTRING field refers to a byte string and is stored in the underlying JCo and ABAP runtimes as an 8-byte value. It corresponds to the ABAP type Y. The value of the STRING field is represented in Java as a byte[] object. Complex field types A complex field may be either a structure or table field type. The following table summarizes these complex field types. Field Type Corresponding Java Type Byte Length Unicode Byte Length Number Decimals Digits Description STRUCTURE org.fusesource.camel.component.sap.model.rfc.Structure Total of individual field byte lengths Total of individual field Unicode byte lengths - ABAP Type 'u' & 'v': Heterogeneous Structure TABLE org.fusesource.camel.component.sap.model.rfc.Table Byte length of row structure Unicode byte length of row structure - ABAP Type 'h': Table Structure field types A STRUCTURE field contains a structure object and is stored in the underlying JCo and ABAP runtimes as an ABAP structure record. It corresponds to either an ABAP type u or v . The value of a STRUCTURE field is represented in Java as a structure object with the interface org.fusesource.camel.component.sap.model.rfc.Structure . Table field types A TABLE field contains a table object and is stored in the underlying JCo and ABAP runtimes as an ABAP internal table. It corresponds to the ABAP type h . The value of the field is represented in Java by a table object with the interface org.fusesource.camel.component.sap.model.rfc.Table . Table objects A table object is a homogeneous list data structure containing rows of structure objects with the same structure. This interface extends both the java.util.List and org.eclipse.emf.ecore.EObject interfaces. public interface Table<S extends Structure> extends org.eclipse.emf.ecore.EObject, java.util.List<S> { /** * Creates and adds table row at end of row list */ S add(); /** * Creates and adds table row at index in row list */ S add(int index); } The list of rows in a table object are accessed and managed using the standard methods defined in the list interface. In addition, the table interface provides two factory methods for creating and adding structure objects to the row list. Table objects are implemented in the component runtime using the Eclipse Modeling Framework (EMF) and support that framework's EObject interface. Instances of a table object have attached metadata which define and restrict the structure and contents of the rows it provides. This metadata can be accessed and introspected using the standard methods provided by EMF. Please refer to the EMF documentation for further details. Note Attempts to add or set a row structure value of the wrong type throws an exception. 290.10. Message Body for IDoc IDoc message type When using one of the IDoc Camel SAP endpoints, the type of the message body depends on which particular endpoint you are using. For a sap-idoc-destination endpoint or a sap-qidoc-destination endpoint, the message body is of Document type: For a sap-idoclist-destination endpoint, a sap-qidoclist-destination endpoint, or a sap-idoclist-server endpoint, the message body is of DocumentList type: The IDoc document model For the Camel SAP component, an IDoc document is modelled using the Eclipse Modelling Framework (EMF), which provides a wrapper API around the underlying SAP IDoc API. The most important types in this model are: The Document type represents an IDoc document instance. In outline, the Document interface exposes the following methods: The following kinds of method are exposed by the Document interface: Methods for accessing the control record Most of the methods are for accessing or modifying field values of the IDoc control record. These methods are of the form AttributeName , AttributeName , where AttributeName is the name of a field value (see Table 290.2, "IDoc Document Attributes" ). Method for accessing the document contents The getRootSegment method provides access to the document contents (IDoc data records), returning the contents as a Segment object. Each Segment object can contain an arbitrary number of child segments, and the segments can be nested to an arbitrary degree. Note The precise layout of the segment hierarchy is defined by the particular IDoc type of the document. When creating (or reading) a segment hierarchy, therefore, you must be sure to follow the exact structure as defined by the IDoc type. The Segment type is used to access the data records of the IDoc document, where the segments are laid out in accordance with the structure defined by the document's IDoc type. In outline, the Segment interface exposes the following methods: The getChildren(String segmentType) method is particularly useful for adding new (nested) children to a segment. It returns an object of type, SegmentList , which is defined as follows: Hence, to create a data record of E1SCU_CRE type, you could use Java code like the following: Segment rootSegment = document.getRootSegment(); Segment E1SCU_CRE_Segment = rootSegment.getChildren("E1SCU_CRE").add(); How an IDoc is related to a Document object According to the SAP documentation, an IDoc document consists of the following main parts: Control record The control record (which contains the metadata for the IDoc document) is represented by the attributes on the Document object - see Table 290.2, "IDoc Document Attributes" for details. Data records The data records are represented by the Segment objects, which are constructed as a nested hierarchy of segments. You can access the root segment through the Document.getRootSegment method. Status records In the Camel SAP component, the status records are not represented by the document model. But you do have access to the latest status value through the status attribute on the control record. Example of creating a Document instance For example, Example 290.1, "Creating an IDoc Document in Java" shows how to create an IDoc document with the IDoc type, FLCUSTOMER_CREATEFROMDATA01 , using the IDoc model API in Java. Example 290.1. Creating an IDoc Document in Java Document attributes Table 290.2, "IDoc Document Attributes" shows the control record attributes that you can set on the Document object. Table 290.2. IDoc Document Attributes Attribute Length SAP Field Description archiveKey 70 ARCKEY EDI archive key client 3 MANDT Client creationDate 8 CREDAT Date IDoc was created creationTime 6 CRETIM Time IDoc was created direction 1 DIRECT Direction eDIMessage 14 REFMES Reference to message eDIMessageGroup 14 REFGRP Reference to message group eDIMessageType 6 STDMES EDI message type eDIStandardFlag 1 STD EDI standard eDIStandardVersion 6 STDVRS Version of EDI standard eDITransmissionFile 14 REFINT Reference to interchange file iDocCompoundType 8 DOCTYP IDoc type iDocNumber 16 DOCNUM IDoc number iDocSAPRelease 4 DOCREL SAP Release of IDoc iDocType 30 IDOCTP Name of basic IDoc type iDocTypeExtension 30 CIMTYP Name of extension type messageCode 3 MESCOD Logical message code messageFunction 3 MESFCT Logical message function messageType 30 MESTYP Logical message type outputMode 1 OUTMOD Output mode recipientAddress 10 RCVSAD Receiver address (SADR) recipientLogicalAddress 70 RCVLAD Logical address of receiver recipientPartnerFunction 2 RCVPFC Partner function of receiver recipientPartnerNumber 10 RCVPRN Partner number of receiver recipientPartnerType 2 RCVPRT Partner type of receiver recipientPort 10 RCVPOR Receiver port (SAP System, EDI subsystem) senderAddress SNDSAD Sender address (SADR) senderLogicalAddress 70 SNDLAD Logical address of sender senderPartnerFunction 2 SNDPFC Partner function of sender senderPartnerNumber 10 SNDPRN Partner number of sender senderPartnerType 2 SNDPRT Partner type of sender senderPort 10 SNDPOR Sender port (SAP System, EDI subsystem) serialization 20 SERIAL EDI/ALE: Serialization field status 2 STATUS Status of IDoc testFlag 1 TEST Test flag Setting document attributes in Java When setting the control record attributes in Java (from Table 290.2, "IDoc Document Attributes" ), the usual convention for Java bean properties is followed. That is, a name attribute can be accessed through the getName and setName methods, for getting and setting the attribute value. For example, the iDocType , iDocTypeExtension , and messageType attributes can be set as follows on a Document object: // Java document.setIDocType("FLCUSTOMER_CREATEFROMDATA01"); document.setIDocTypeExtension(""); document.setMessageType("FLCUSTOMER_CREATEFROMDATA"); Setting document attributes in XML When setting the control record attributes in XML, the attributes must be set on the idoc:Document element. For example, the iDocType , iDocTypeExtension , and messageType attributes can be set as follows: <?xml version="1.0" encoding="ASCII"?> <idoc:Document ... iDocType="FLCUSTOMER_CREATEFROMDATA01" iDocTypeExtension="" messageType="FLCUSTOMER_CREATEFROMDATA" ... > ... </idoc:Document> 290.11. Transaction Support BAPI transaction model The SAP Component supports the BAPI transaction model for outbound communication with SAP. A destination endpoint with a URL containing the transacted option set to true initiates a stateful session on the outbound connection of the endpoint and registers a Camel Synchronization object with the exchange. This synchronization object calls the BAPI service method BAPI_TRANSACTION_COMMIT and end the stateful session when the processing of the message exchange is complete. If the processing of the message exchange fails, the synchronization object calls the BAPI server method BAPI_TRANSACTION_ROLLBACK and end the stateful session. RFC transaction model The tRFC protocol accomplishes an AT-MOST-ONCE delivery and processing guarantee by identifying each transactional request with a unique transaction identifier (TID). A TID accompanies each request sent in the protocol. A sending application using the tRFC protocol must identify each instance of a request with a unique TID when sending the request. An application may send a request with a given TID multiple times, but the protocol ensures that the request is delivered and processed in the receiving system at most once. An application may choose to resend a request with a given TID when encountering a communication or system error when sending the request, and is thus in doubt as to whether that request was delivered and processed in the receiving system. By resending a request when encountering an communication error, a client application using the tRFC protocol can thus ensure EXACTLY-ONCE delivery and processing guarantees for its request. Which transaction model to use? A BAPI transaction is an application level transaction, in the sense that it imposes ACID guarantees on the persistent data changes performed by a BAPI method or RFC function in the SAP database. An RFC transaction is a communication transaction, in the sense that it imposes delivery guarantees (AT-MOST-ONCE, EXACTLY-ONCE, EXACTLY-ONCE-IN-ORDER) on requests to a BAPI method and/or RFC function. Transactional RFC destination endpoints The following destination endpoints support RFC transactions: sap-trfc-destination sap-qrfc-destination A single Camel route can include multiple transactional RFC destination endpoints, sending messages to multiple RFC destinations and even sending messages to the same RFC destination multiple times. This implies that the Camel SAP component potentially needs to keep track of many transaction IDs (TIDs) for each Exchange object passing along a route. Now if the route processing fails and must be retried, the situation gets quite complicated. The RFC transaction semantics demand that each RFC destination along the route must be invoked using the same TID that was used the first time around (and where the TIDs for each of the destinations are distinct from each other). In other words, the Camel SAP component must keep track of which TID was used at which point along the route, and remember this information, so that the TIDs can be replayed in the correct order. By default, Camel does not provide a mechanism that enables an Exchange to know where it is in a route. To provide such a mechanism, it is necessary to install the CurrentProcessorDefinitionInterceptStrategy interceptor into the Camel runtime. This interceptor must be installed into the Camel runtime, to to keep track of the TIDs in a route with the Camel SAP component. For details of how to configure the interceptor, see the section called "Interceptor for tRFC and qRFC destinations" . Transactional RFC server endpoints The following server endpoints support RFC transactions: sap-trfc-server When a Camel exchange processing a transactional request encounters a processing error, Camel handles the processing error through its standard error handling mechanisms. If the Camel route processing the exchange is configured to propagate the error back to the caller, the SAP server endpoint that initiated the exchange takes note of the failure and the sending SAP system is notified of the error. The sending SAP system can then respond by sending another transaction request with the same TID to process the request again. 290.12. XML Serialization for RFC Overview SAP request and response objects support an XML serialization format which enable these objects to be serialized to and from an XML document. XML namespace Each RFC in a repository defines a specific XML namespace for the elements which compose the serialized forms of its Request and Response objects. The form of this namespace URL is as follows: RFC namespace URLs have a common http://sap.fusesource.org/rfc prefix followed by the name of the repository in which the RFC's metadata is defined. The final component in the URL is the name of the RFC itself. Request and response XML documents An SAP request object is serialized into an XML document with the root element of that document named Request and scoped by the namespace of the request's RFC. <?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Request xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> ... </BOOK_FLIGHT:Request> An SAP response object is serialized into an XML document with the root element of that document named Response and scoped by the namespace of the response's RFC. <?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Response xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> ... </BOOK_FLIGHT:Response> Structure fields Structure fields in parameter lists or nested structures are serialized as elements. The element name of the serialized structure corresponds to the field name of the structure within the enclosing parameter list, structure or table row entry it resides. <BOOK_FLIGHT:FLTINFO xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> ... </BOOK_FLIGHT:FLTINFO> Note The type name of the structure element in the RFC namespace corresponds to the name of the record metadata object which defines the structure, as in the following example: <xs:schema targetNamespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> xmlns:xs="http://www.w3.org/2001/XMLSchema"> ... <xs:complexType name="FLTINFO_STRUCTURE"> ... </xs:complexType> ... </xs:schema> This distinction is important when specifying a JAXB bean to marshal and unmarshal the structure as is seen in Section 290.14.3, "Example 3: Handling Requests from SAP" . Table fields Table fields in parameter lists or nested structures are serialized as elements. The element name of the serialized structure corresponds to the field name of the table within the enclosing parameter list, structure, or table row entry it resides. The table element contains a series of row elements to hold the serialized values of the table's row entries. <BOOK_FLIGHT:CONNINFO xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> <row ... > ... </row> ... <row ... > ... </row> </BOOK_FLIGHT:CONNINFO> Note The type name of the table element in the RFC namespace corresponds to the name of the record metadata object which defines the row structure of the table suffixed by _TABLE . The type name of the table row element in the RFC name corresponds to the name of the record metadata object which defines the row structure of the table, as in the following example: <xs:schema targetNamespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT" xmlns:xs="http://www.w3.org/2001/XMLSchema"> ... <xs:complextType name="CONNECTION_INFO_STRUCTURE_TABLE"> <xs:sequence> <xs:element name="row" minOccures="0" maxOccurs="unbounded" type="CONNECTION_INFO_STRUCTURE"/> ... <xs:sequence> </xs:sequence> </xs:complexType> <xs:complextType name="CONNECTION_INFO_STRUCTURE"> ... </xs:complexType> ... </xs:schema> This distinction is important when specifying a JAXB bean to marshal and unmarshal the structure as is seen in Section 290.14.3, "Example 3: Handling Requests from SAP" . Elementary fields Elementary fields in parameter lists or nested structures are serialized as attributes on the element of the enclosing parameter list or structure. The attribute name of the serialized field corresponds to the field name of the field within the enclosing parameter list, structure, or table row entry it resides, as in the following example: <?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Request xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT" CUSTNAME="James Legrand" PASSFORM="Mr" PASSNAME="Travelin Joe" PASSBIRTH="1990-03-17T00:00:00.000-0500" FLIGHTDATE="2014-03-19T00:00:00.000-0400" TRAVELAGENCYNUMBER="00000110" DESTINATION_FROM="SFO" DESTINATION_TO="FRA"/> Date and time formats Date and Time fields are serialized into attribute values using the following format: Date fields is serialized with only the year, month, day and timezone components set: DEPDATE="2014-03-19T00:00:00.000-0400" Time fields is serialized with only the hour, minute, second, millisecond and timezone components set: DEPTIME="1970-01-01T16:00:00.000-0500" 290.13. XML Serialization for IDoc Overview An IDoc message body can be serialized into an XML string format, with the help of a built-in type converter. XML namespace Each serialized IDoc is associated with an XML namespace, which has the following general format: Both the repositoryName (name of the remote SAP metadata repository) and the idocType (IDoc document type) are mandatory, but the other components of the namespace can be left blank. For example, you could have an XML namespace like the following: http://sap.fusesource.org/idoc/MY_REPO/FLCUSTOMER_CREATEFROMDATA01/// Built-in type converter The Camel SAP component has a built-in type converter, which is capable of converting a Document object or a DocumentList object to and from a String type. For example, to serialize a Document object to an XML string, you can simply add the following line to a route in XML DSL: <convertBodyTo type="java.lang.String"/> You can also use this approach to a serialized XML message into a Document object. For example, given that the current message body is a serialized XML string, you can convert it back into a Document object by adding the following line to a route in XML DSL: <convertBodyTo type="org.fusesource.camel.component.sap.model.idoc.Document"/> Sample IDoc message body in XML format When you convert an IDoc message to a String , it is serialized into an XML document, where the root element is either idoc:Document (for a single document) or idoc:DocumentList (for a list of documents). Example 290.2, "IDoc Message Body in XML" shows a single IDoc document that has been serialized to an idoc:Document element. Example 290.2. IDoc Message Body in XML <?xml version="1.0" encoding="ASCII"?> <idoc:Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:FLCUSTOMER_CREATEFROMDATA01---="http://sap.fusesource.org/idoc/XXX/FLCUSTOMER_CREATEFROMDATA01///" xmlns:idoc="http://sap.fusesource.org/idoc" creationDate="2015-01-28T12:39:13.980-0500" creationTime="2015-01-28T12:39:13.980-0500" iDocType="FLCUSTOMER_CREATEFROMDATA01" iDocTypeExtension="" messageType="FLCUSTOMER_CREATEFROMDATA" recipientPartnerNumber="QUICKCLNT" recipientPartnerType="LS" senderPartnerNumber="QUICKSTART" senderPartnerType="LS"> <rootSegment xsi:type="FLCUSTOMER_CREATEFROMDATA01---:ROOT" document="/"> <segmentChildren parent="//@rootSegment"> <E1SCU_CRE parent="//@rootSegment" document="/"> <segmentChildren parent="//@rootSegment/@segmentChildren/@E1SCU_CRE.0"> <E1BPSCUNEW parent="//@rootSegment/@segmentChildren/@E1SCU_CRE.0" document="/" CUSTNAME="Fred Flintstone" FORM="Mr." STREET="123 Rubble Lane" POSTCODE="01234" CITY="Bedrock" COUNTR="US" PHONE="800-555-1212" EMAIL="fred@bedrock.com" CUSTTYPE="P" DISCOUNT="005" LANGU="E"/> </segmentChildren> </E1SCU_CRE> </segmentChildren> </rootSegment> </idoc:Document> 290.14. SAP Examples 290.14.1. Example 1: Reading Data from SAP Overview This example demonstrates a route that reads FlightCustomer business object data from SAP. The route invokes the FlightCustomer BAPI method, BAPI_FLCUST_GETLIST , using a SAP synchronous RFC destination endpoint to retrieve the data. Java DSL for route The Java DSL for the example route is as follows: from("direct:getFlightCustomerInfo") .to("bean:createFlightCustomerGetListRequest") .to("sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST") .to("bean:returnFlightCustomerInfo"); XML DSL for route And the Spring DSL for the same route is as follows: <route> <from uri="direct:getFlightCustomerInfo"/> <to uri="bean:createFlightCustomerGetListRequest"/> <to uri="sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST"/> <to uri="bean:returnFlightCustomerInfo"/> </route> createFlightCustomerGetListRequest bean The createFlightCustomerGetListRequest bean is responsible for building a SAP request object in its exchange method used in the RFC call of the subsequent SAP endpoint . The following code snippet demonstrates the sequence of operations to build the request object: public void create(Exchange exchange) throws Exception { // Get SAP Endpoint to be called from context. SapSynchronousRfcDestinationEndpoint endpoint = exchange.getContext().getEndpoint("sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST", SapSynchronousRfcDestinationEndpoint.class); // Retrieve bean from message containing Flight Customer name to // look up. BookFlightRequest bookFlightRequest = exchange.getIn().getBody(BookFlightRequest.class); // Create SAP Request object from target endpoint. Structure request = endpoint.getRequest(); // Add Customer Name to request if set if (bookFlightRequest.getCustomerName() != null && bookFlightRequest.getCustomerName().length() > 0) { request.put("CUSTOMER_NAME", bookFlightRequest.getCustomerName()); } } else { throw new Exception("No Customer Name"); } // Put request object into body of exchange message. exchange.getIn().setBody(request); } returnFlightCustomerInfo bean The returnFlightCustomerInfo bean is responsible for extracting data from the SAP response object in its exchange method that it receives from the SAP endpoint. The following code snippet demonstrates the sequence of operations to extract the data from the response object: public void createFlightCustomerInfo(Exchange exchange) throws Exception { // Retrieve SAP response object from body of exchange message. Structure flightCustomerGetListResponse = exchange.getIn().getBody(Structure.class); if (flightCustomerGetListResponse == null) { throw new Exception("No Flight Customer Get List Response"); } // Check BAPI return parameter for errors @SuppressWarnings("unchecked") Table<Structure> bapiReturn = flightCustomerGetListResponse.get("RETURN", Table.class); Structure bapiReturnEntry = bapiReturn.get(0); if (bapiReturnEntry.get("TYPE", String.class) != "S") { String message = bapiReturnEntry.get("MESSAGE", String.class); throw new Exception("BAPI call failed: " + message); } // Get customer list table from response object. @SuppressWarnings("unchecked") Table<? extends Structure> customerList = flightCustomerGetListResponse.get("CUSTOMER_LIST", Table.class); if (customerList == null || customerList.size() == 0) { throw new Exception("No Customer Info."); } // Get Flight Customer data from first row of table. Structure customer = customerList.get(0); // Create bean to hold Flight Customer data. FlightCustomerInfo flightCustomerInfo = new FlightCustomerInfo(); // Get customer id from Flight Customer data and add to bean. String customerId = customer.get("CUSTOMERID", String.class); if (customerId != null) { flightCustomerInfo.setCustomerNumber(customerId); } ... // Put bean into body of exchange message. exchange.getIn().setHeader("flightCustomerInfo", flightCustomerInfo); } 290.14.2. Example 2: Writing Data to SAP Overview This example demonstrates a route that creates a FlightTrip business object instance in SAP. The route invokes the FlightTrip BAPI method, BAPI_FLTRIP_CREATE , using a destination endpoint to create the object. Java DSL for route The Java DSL for the example route is as follows: from("direct:createFlightTrip") .to("bean:createFlightTripRequest") .to("sap-srfc-destination:nplDest:BAPI_FLTRIP_CREATE?transacted=true") .to("bean:returnFlightTripResponse"); XML DSL for route And the Spring DSL for the same route is as follows: <route> <from uri="direct:createFlightTrip"/> <to uri="bean:createFlightTripRequest"/> <to uri="sap-srfc-destination:nplDest:BAPI_FLTRIP_CREATE?transacted=true"/> <to uri="bean:returnFlightTripResponse"/> </route> Transaction support Note The URL for the SAP endpoint has the transacted option set to true . As discussed in Section 290.11, "Transaction Support" , when this option is enabled the endpoint ensures that a SAP transaction session has been initiated before invoking the RFC call. Because this endpoint's RFC creates new data in SAP, this option is necessary to make the route's changes permanent in SAP. Populating request parameters The createFlightTripRequest and returnFlightTripResponse beans are responsible for populating request parameters into the SAP request and extracting response parameters from the SAP response respectively, following the same sequence of operations as demonstrated in the example. 290.14.3. Example 3: Handling Requests from SAP Overview This example demonstrates a route that handles a request from SAP to the BOOK_FLIGHT RFC, which is implemented by the route. In addition, it demonstrates the component's XML serialization support, using JAXB to unmarshal and marshal SAP request objects and response objects to custom beans. This route creates a FlightTrip business object on behalf of a travel agent, FlightCustomer . The route first unmarshals the SAP request object received by the SAP server endpoint into a custom JAXB bean. This custom bean is then multicasted in the exchange to three sub-routes, which gather the travel agent, flight connection, and passenger information required to create the flight trip. The final sub-route creates the flight trip object in SAP, as demonstrated in the example. The final sub-route also creates and returns a custom JAXB bean which is marshaled into a SAP response object and returned by the server endpoint. Java DSL for route The Java DSL for the example route is as follows: DataFormat jaxb = new JaxbDataFormat("org.fusesource.sap.example.jaxb"); from("sap-srfc-server:nplserver:BOOK_FLIGHT") .unmarshal(jaxb) .multicast() .to("direct:getFlightConnectionInfo", "direct:getFlightCustomerInfo", "direct:getPassengerInfo") .end() .to("direct:createFlightTrip") .marshal(jaxb); XML DSL for route And the XML DSL for the same route is as follows: <route> <from uri="sap-srfc-server:nplserver:BOOK_FLIGHT"/> <unmarshal> <jaxb contextPath="org.fusesource.sap.example.jaxb"/> </unmarshal> <multicast> <to uri="direct:getFlightConnectionInfo"/> <to uri="direct:getFlightCustomerInfo"/> <to uri="direct:getPassengerInfo"/> </multicast> <to uri="direct:createFlightTrip"/> <marshal> <jaxb contextPath="org.fusesource.sap.example.jaxb"/> </marshal> </route> BookFlightRequest bean The following listing illustrates a JAXB bean which unmarshals from the serialized form of a SAP BOOK_FLIGHT request object: @XmlRootElement(name="Request", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class BookFlightRequest { @XmlAttribute(name="CUSTNAME") private String customerName; @XmlAttribute(name="FLIGHTDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date flightDate; @XmlAttribute(name="TRAVELAGENCYNUMBER") private String travelAgencyNumber; @XmlAttribute(name="DESTINATION_FROM") private String startAirportCode; @XmlAttribute(name="DESTINATION_TO") private String endAirportCode; @XmlAttribute(name="PASSFORM") private String passengerFormOfAddress; @XmlAttribute(name="PASSNAME") private String passengerName; @XmlAttribute(name="PASSBIRTH") @XmlJavaTypeAdapter(DateAdapter.class) private Date passengerDateOfBirth; @XmlAttribute(name="CLASS") private String flightClass; ... } BookFlightResponse bean The following listing illustrates a JAXB bean which marshals to the serialized form of a SAP BOOK_FLIGHT response object: @XmlRootElement(name="Response", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class BookFlightResponse { @XmlAttribute(name="TRIPNUMBER") private String tripNumber; @XmlAttribute(name="TICKET_PRICE") private BigDecimal ticketPrice; @XmlAttribute(name="TICKET_TAX") private BigDecimal ticketTax; @XmlAttribute(name="CURRENCY") private String currency; @XmlAttribute(name="PASSFORM") private String passengerFormOfAddress; @XmlAttribute(name="PASSNAME") private String passengerName; @XmlAttribute(name="PASSBIRTH") @XmlJavaTypeAdapter(DateAdapter.class) private Date passengerDateOfBirth; @XmlElement(name="FLTINFO") private FlightInfo flightInfo; @XmlElement(name="CONNINFO") private ConnectionInfoTable connectionInfo; ... } Note The complex parameter fields of the response object are serialized as child elements of the response. FlightInfo bean The following listing illustrates a JAXB bean which marshals to the serialized form of the complex structure parameter FLTINFO : @XmlRootElement(name="FLTINFO", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class FlightInfo { @XmlAttribute(name="FLIGHTTIME") private String flightTime; @XmlAttribute(name="CITYFROM") private String cityFrom; @XmlAttribute(name="DEPDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date departureDate; @XmlAttribute(name="DEPTIME") @XmlJavaTypeAdapter(DateAdapter.class) private Date departureTime; @XmlAttribute(name="CITYTO") private String cityTo; @XmlAttribute(name="ARRDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date arrivalDate; @XmlAttribute(name="ARRTIME") @XmlJavaTypeAdapter(DateAdapter.class) private Date arrivalTime; ... } ConnectionInfoTable bean The following listing illustrates a JAXB bean which marshals to the serialized form of the complex table parameter, CONNINFO . Note The name of the root element type of the JAXB bean corresponds to the name of the row structure type suffixed with _TABLE and the bean contains a list of row elements. @XmlRootElement(name="CONNINFO_TABLE", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class ConnectionInfoTable { @XmlElement(name="row") List<ConnectionInfo> rows; ... } ConnectionInfo bean The following listing illustrates a JAXB bean, which marshals to the serialized form of the above tables row elements: @XmlRootElement(name="CONNINFO", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class ConnectionInfo { @XmlAttribute(name="CONNID") String connectionId; @XmlAttribute(name="AIRLINE") String airline; @XmlAttribute(name="PLANETYPE") String planeType; @XmlAttribute(name="CITYFROM") String cityFrom; @XmlAttribute(name="DEPDATE") @XmlJavaTypeAdapter(DateAdapter.class) Date departureDate; @XmlAttribute(name="DEPTIME") @XmlJavaTypeAdapter(DateAdapter.class) Date departureTime; @XmlAttribute(name="CITYTO") String cityTo; @XmlAttribute(name="ARRDATE") @XmlJavaTypeAdapter(DateAdapter.class) Date arrivalDate; @XmlAttribute(name="ARRTIME") @XmlJavaTypeAdapter(DateAdapter.class) Date arrivalTime; ... }

Commands:
<dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap</artifactId> <version>x.x.x</version> <dependency>
:experimental: // Standard document attributes to be used in the documentation // // The following are shared by all documents :toc: :toclevels: 4 :numbered:
org.osgi.framework.system.packages.extra ... , com.sap.conn.idoc, com.sap.conn.idoc.jco, com.sap.conn.jco, com.sap.conn.jco.ext, com.sap.conn.jco.monitor, com.sap.conn.jco.rt, com.sap.conn.jco.server
JBossFuse:karaf@root> features:install camel-sap
cp sapjco3.jar sapidoc3.jar USDJBOSS_HOME/modules/system/layers/fuse/com/sap/conn/jco/main/ mkdir -p USDJBOSS_HOME/modules/system/layers/fuse/com/sap/conn/jco/main/lib/linux-x86_64 cp libsapjco3.so USDJBOSS_HOME/modules/system/layers/fuse/com/sap/conn/jco/main/lib/linux-x86_64/
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.1" name="org.wildfly.camel.extras"> <dependencies> <module name="org.fusesource.camel.component.sap" export="true" services="export" /> </dependencies> </module>
<dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap-starter</artifactId> <exclusions> <exclusion> <groupId>com.sap.conn.idoc</groupId> <artifactId>sapidoc3</artifactId> </exclusion> <exclusion> <groupId>com.sap.conn.jco</groupId> <artifactId>sapjco3</artifactId> </exclusion> </exclusions> </dependency>
src └── lib └── amd64.com.sap.conn ├── idoc │ └── sapidoc3.jar └── jco ├── sapjco3.jar └── sapjco3.so
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <Class-Path>lib/USD{os.arch}/sapjco3.jar lib/USD{os.arch}/sapidoc3.jar</Class-Path> </manifestEntries> </archive> </configuration> </plugin>
<plugin> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-resources01</id> <phase>process-classes</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>USD{basedir}/target/lib</outputDirectory> <encoding>UTF-8</encoding> <resources> <resource> <directory>USD{basedir}/lib</directory> <includes> <include>**/**</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin>
new-build --binary=true --image-stream="<current_Fuse_Java_OpenShift_Imagestream_version>" --name=<application_name> -e "ARTIFACT_COPY_ARGS=-a ." -e "MAVEN_ARGS_APPEND=<additional_args> -e "ARTIFACT_DIR=<relative_path_of_target_directory>"
new-build --binary=true --image-stream="fuse7-java-openshift:1.4" --name=sapik6 -e "ARTIFACT_COPY_ARGS=-a ." -e "MAVEN_ARGS_APPEND=-pl spring-boot/sap-srfc-destination-spring-boot" -e "ARTIFACT_DIR=spring-boot/sap-srfc-destination-spring-boot/target"
start-build sapik6 --from-dir=.
new-app --image-stream=<name>:<version>
new-app --image-stream=sapik6:latest
src └── lib └── amd64.com.sap.conn ├── idoc │ └── sapidoc3.jar └── jco ├── sapjco3.jar └── sapjco3.so
<dependency> <groupId>org.fusesource</groupId> <artifactId>camel-sap-starter</artifactId> <exclusions> <exclusion> <groupId>com.sap.conn.idoc</groupId> <artifactId>sapidoc3</artifactId> </exclusion> <exclusion> <groupId>com.sap.conn.jco</groupId> <artifactId>sapjco3</artifactId> </exclusion> </exclusions> </dependency>
<resources> <resource> <directory>src/lib/USD{os.arch}/com/sap/conn/idoc</directory> <targetPath>BOOT-INF/lib</targetPath> <includes> <include>*.jar</include> </includes> </resource> <resource> <directory>src/lib/USD{os.arch}/com/sap/conn/jco</directory> <targetPath>BOOT-INF/lib</targetPath> <includes> <include>*.jar</include> </includes> </resource> </resources>
<plugin> <groupId>org.eclipse.jkube</groupId> <artifactId>openshift-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <images> <image> <name>USD{project.artifactId}:USD{project.version}</name> <build> <from>USD{java.docker.image}</from> <assembly> <targetDir>/deployments</targetDir> <layers> <layer> <id>static-files</id> <fileSets> <fileSet> <directory>src/lib/USD{os.arch}/com/sap/conn/jco</directory> <outputDirectory>static</outputDirectory> <includes> <include>*.so</include> </includes> </fileSet> </fileSets> </layer> </layers> </assembly> </build> </image> </images> </configuration> <executions> <execution> <goals> <goal>resource</goal> <goal>build</goal> <goal>apply</goal> </goals> </execution> </executions> </plugin>
cd <sap_application_path>
new-project streams
import-image streams/fuse7-java-openshift:1.11 --from=registry.redhat.io/fuse7/fuse-java-openshift-rhel8:1.11-32 --confirm -n streams (JDK8)
new-project <your_project>
mvn clean oc:deploy -Djkube.docker.imagePullPolicy=Always -Popenshift -Djkube.generator.from=streams/fuse7-java-openshift:1.11 -Djkube.resourceDir=./src/main/jkube -Djkube.openshiftManifest=target/classes/META-INF/jkube/openshift.yml -Djkube.generator.fromMode=istag
sap-srfc-destination: destinationName : rfcName sap-trfc-destination: destinationName : rfcName sap-qrfc-destination: destinationName : queueName : rfcName sap-srfc-server: serverName : rfcName [? options ] sap-trfc-server: serverName : rfcName [? options ]
sap-idoc-destination: destinationName : idocType [: idocTypeExtension [: systemRelease [: applicationRelease ]]] sap-idoclist-destination: destinationName : idocType [: idocTypeExtension [: systemRelease [: applicationRelease ]]] sap-qidoc-destination: destinationName : queueName : idocType [: idocTypeExtension [: systemRelease [: applicationRelease ]]] sap-qidoclist-destination: destinationName : queueName : idocType [: idocTypeExtension [: systemRelease [: applicationRelease ]]] sap-idoclist-server: serverName : idocType [: idocTypeExtension [: systemRelease [: applicationRelease ]]][? options ]
<?xml version="1.0" encoding="UTF-8"?> <blueprint ... > <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> <property name="serverDataStore"> <map> <entry key="quickstartServer" value-ref="quickstartServerData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="passowrd" /> <property name="lang" value="en" /> </bean> <!-- Configures an Inbound SAP Connection --> <!-- *** Please enter the connection property values for your environment ** --> <bean id="quickstartServerData" class="org.fusesource.camel.component.sap.model.rfc.impl.ServerDataImpl"> <property name="gwhost" value="example.com" /> <property name="gwserv" value="3300" /> <!-- Do not change the following property values --> <property name="progid" value="QUICKSTART" /> <property name="repositoryDestination" value="quickstartDest" /> <property name="connectionCount" value="2" /> </bean> </blueprint>
<?xml version="1.0" encoding="UTF-8"?> <blueprint ... > <!-- Create interceptor to support tRFC processing --> <bean id="currentProcessorDefinitionInterceptor" class="org.fusesource.camel.component.sap.CurrentProcessorDefinitionInterceptStrategy" /> <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="password" /> <property name="lang" value="en" /> </bean> </blueprint>
sap-srfc-destination:quickstartDest:BAPI_FLCUST_GETLIST
<?xml version="1.0" encoding="UTF-8"?> <blueprint ... > <!-- Configures the Inbound and Outbound SAP Connections --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="destinationDataStore"> <map> <entry key="quickstartDest" value-ref="quickstartDestinationData" /> </map> </property> <property name="serverDataStore"> <map> <entry key="quickstartServer" value-ref="quickstartServerData" /> </map> </property> </bean> <!-- Configures an Outbound SAP Connection --> <!-- *** Please enter the connection property values for your environment *** --> <bean id="quickstartDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl"> <property name="ashost" value="example.com" /> <property name="sysnr" value="00" /> <property name="client" value="000" /> <property name="user" value="username" /> <property name="passwd" value="passowrd" /> <property name="lang" value="en" /> </bean> <!-- Configures an Inbound SAP Connection --> <!-- *** Please enter the connection property values for your environment ** --> <bean id="quickstartServerData" class="org.fusesource.camel.component.sap.model.rfc.impl.ServerDataImpl"> <property name="gwhost" value="example.com" /> <property name="gwserv" value="3300" /> <!-- Do not change the following property values --> <property name="progid" value="QUICKSTART" /> <property name="repositoryDestination" value="quickstartDest" /> <property name="connectionCount" value="2" /> </bean> </blueprint>
sap-srfc-server:quickstartServer:BAPI_FLCUST_GETLIST
<?xml version="1.0" encoding="UTF-8"?> <blueprint ... > <!-- Configures the sap-srfc-server component --> <bean id="sap-configuration" class="org.fusesource.camel.component.sap.SapConnectionConfiguration"> <property name="repositoryDataStore"> <map> <entry key="nplServer" value-ref="nplRepositoryData" /> </map> </property> </bean> <!-- Configures a metadata Repository --> <bean id="nplRepositoryData" class="org.fusesource.camel.component.sap.model.rfc.impl.RepositoryDataImpl"> <property name="functionTemplates"> <map> <entry key="BOOK_FLIGHT" value-ref="bookFlightFunctionTemplate" /> </map> </property> </bean> </blueprint>
<bean id="bookFlightFunctionTemplate" class="org.fusesource.camel.component.sap.model.rfc.impl.FunctionTemplateImpl"> <property name="importParameterList"> <list> </list> </property> <property name="changingParameterList"> <list> </list> </property> <property name="exportParameterList"> <list> </list> </property> <property name="tableParameterList"> <list> </list> </property> <property name="exceptionList"> <list> </list> </property> </bean>
<bean class="org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMetaDataImpl"> <property name="name" value="TICKET_PRICE" /> <property name="type" value="BCD" /> <property name="byteLength" value="12" /> <property name="unicodeByteLength" value="24" /> <property name="decimals" value="2" /> <property name="optional" value="true" /> </bean>
<bean class="org.fusesource.camel.component.sap.model.rfc.impl.ListFieldMetaDataImpl"> <property name="name" value="CONNINFO" /> <property name="type" value="TABLE" /> <property name="recordMetaData" ref="connectionInfo" /> </bean>
<bean id="connectionInfo" class="org.fusesource.camel.component.sap.model.rfc.impl.RecordMetaDataImpl"> <property name="name" value="CONNECTION_INFO" /> <property name="recordFieldMetaData"> <list> </list> </property> </bean>
<bean class="org.fusesource.camel.component.sap.model.rfc.impl.FieldMetaDataImpl"> <property name="name" value="ARRDATE" /> <property name="type" value="DATE" /> <property name="byteLength" value="8" /> <property name="unicodeByteLength" value="16" /> <property name="byteOffset" value="85" /> <property name="unicodeByteOffset" value="170" /> </bean>
<bean class="org.fusesource.camel.component.sap.model.rfc.impl.FieldMetaDataImpl"> <property name="name" value="FLTINFO" /> <property name="type" value="STRUCTURE" /> <property name="byteOffset" value="0" /> <property name="unicodeByteOffset" value="0" /> <property name="recordMetaData" ref="flightInfo" /> </bean>
public class SAPEndpoint { public Structure getRequest() throws Exception; public Structure getResponse() throws Exception; }
public interface Structure extends org.eclipse.emf.ecore.EObject, java.util.Map<String, Object> { <T> T get(Object key, Class<T> type); }
public interface Table<S extends Structure> extends org.eclipse.emf.ecore.EObject, java.util.List<S> { /** * Creates and adds table row at end of row list */ S add(); /** * Creates and adds table row at index in row list */ S add(int index); }
org.fusesource.camel.component.sap.model.idoc.Document
org.fusesource.camel.component.sap.model.idoc.DocumentList
org.fusesource.camel.component.sap.model.idoc.Document org.fusesource.camel.component.sap.model.idoc.Segment
// Java package org.fusesource.camel.component.sap.model.idoc; public interface Document extends EObject { // Access the field values from the IDoc control record String getArchiveKey(); void setArchiveKey(String value); String getClient(); void setClient(String value); // Access the IDoc document contents Segment getRootSegment(); }
// Java package org.fusesource.camel.component.sap.model.idoc; public interface Segment extends EObject, java.util.Map<String, Object> { // Returns the value of the '<em><b>Parent</b></em>' reference. Segment getParent(); // Return a immutable list of all child segments <S extends Segment> EList<S> getChildren(); // Returns a list of child segments of the specified segment type. <S extends Segment> SegmentList<S> getChildren(String segmentType); EList<String> getTypes(); Document getDocument(); String getDescription(); String getType(); String getDefinition(); int getHierarchyLevel(); String getIdocType(); String getIdocTypeExtension(); String getSystemRelease(); String getApplicationRelease(); int getNumFields(); long getMaxOccurrence(); long getMinOccurrence(); boolean isMandatory(); boolean isQualified(); int getRecordLength(); <T> T get(Object key, Class<T> type); }
// Java package org.fusesource.camel.component.sap.model.idoc; public interface SegmentList<S extends Segment> extends EObject, EList<S> { S add(); S add(int index); }
Segment rootSegment = document.getRootSegment(); Segment E1SCU_CRE_Segment = rootSegment.getChildren("E1SCU_CRE").add();
// Java import org.fusesource.camel.component.sap.model.idoc.Document; import org.fusesource.camel.component.sap.model.idoc.Segment; import org.fusesource.camel.component.sap.util.IDocUtil; import org.fusesource.camel.component.sap.model.idoc.Document; import org.fusesource.camel.component.sap.model.idoc.DocumentList; import org.fusesource.camel.component.sap.model.idoc.IdocFactory; import org.fusesource.camel.component.sap.model.idoc.IdocPackage; import org.fusesource.camel.component.sap.model.idoc.Segment; import org.fusesource.camel.component.sap.model.idoc.SegmentChildren; // // Create a new IDoc instance using the modelling classes // // Get the SAP Endpoint bean from the Camel context. // In this example, it's a 'sap-idoc-destination' endpoint. SapTransactionalIDocDestinationEndpoint endpoint = exchange.getContext().getEndpoint( "bean: SapEndpointBeanID ", SapTransactionalIDocDestinationEndpoint.class ); // The endpoint automatically populates some required control record attributes Document document = endpoint.createDocument() // Initialize additional control record attributes document.setMessageType("FLCUSTOMER_CREATEFROMDATA"); document.setRecipientPartnerNumber("QUICKCLNT"); document.setRecipientPartnerType("LS"); document.setSenderPartnerNumber("QUICKSTART"); document.setSenderPartnerType("LS"); Segment rootSegment = document.getRootSegment(); Segment E1SCU_CRE_Segment = rootSegment.getChildren("E1SCU_CRE").add(); Segment E1BPSCUNEW_Segment = E1SCU_CRE_Segment.getChildren("E1BPSCUNEW").add(); E1BPSCUNEW_Segment.put("CUSTNAME", "Fred Flintstone"); E1BPSCUNEW_Segment.put("FORM", "Mr."); E1BPSCUNEW_Segment.put("STREET", "123 Rubble Lane"); E1BPSCUNEW_Segment.put("POSTCODE", "01234"); E1BPSCUNEW_Segment.put("CITY", "Bedrock"); E1BPSCUNEW_Segment.put("COUNTR", "US"); E1BPSCUNEW_Segment.put("PHONE", "800-555-1212"); E1BPSCUNEW_Segment.put("EMAIL", " fred@bedrock.com "); E1BPSCUNEW_Segment.put("CUSTTYPE", "P"); E1BPSCUNEW_Segment.put("DISCOUNT", "005"); E1BPSCUNEW_Segment.put("LANGU", "E");
// Java document.setIDocType("FLCUSTOMER_CREATEFROMDATA01"); document.setIDocTypeExtension(""); document.setMessageType("FLCUSTOMER_CREATEFROMDATA");
<?xml version="1.0" encoding="ASCII"?> <idoc:Document iDocType="FLCUSTOMER_CREATEFROMDATA01" iDocTypeExtension="" messageType="FLCUSTOMER_CREATEFROMDATA" ... > </idoc:Document>
http://sap.fusesource.org/rfc/<Repository Name>/<RFC Name>
<?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Request xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> </BOOK_FLIGHT:Request>
<?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Response xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> </BOOK_FLIGHT:Response>
<BOOK_FLIGHT:FLTINFO xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> </BOOK_FLIGHT:FLTINFO>
<xs:schema targetNamespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="FLTINFO_STRUCTURE"> </xs:complexType> </xs:schema>
<BOOK_FLIGHT:CONNINFO xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT"> <row ... > ... </row> <row ... > ... </row> </BOOK_FLIGHT:CONNINFO>
<xs:schema targetNamespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complextType name="CONNECTION_INFO_STRUCTURE_TABLE"> <xs:sequence> <xs:element name="row" minOccures="0" maxOccurs="unbounded" type="CONNECTION_INFO_STRUCTURE"/> <xs:sequence> </xs:sequence> </xs:complexType> <xs:complextType name="CONNECTION_INFO_STRUCTURE"> </xs:complexType> </xs:schema>
<?xml version="1.0" encoding="ASCII"?> <BOOK_FLIGHT:Request xmlns:BOOK_FLIGHT="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT" CUSTNAME="James Legrand" PASSFORM="Mr" PASSNAME="Travelin Joe" PASSBIRTH="1990-03-17T00:00:00.000-0500" FLIGHTDATE="2014-03-19T00:00:00.000-0400" TRAVELAGENCYNUMBER="00000110" DESTINATION_FROM="SFO" DESTINATION_TO="FRA"/>
yyyy-MM-dd'T'HH:mm:ss.SSSZ
DEPDATE="2014-03-19T00:00:00.000-0400"
DEPTIME="1970-01-01T16:00:00.000-0500"
http://sap.fusesource.org/idoc/ repositoryName / idocType / idocTypeExtension / systemRelease / applicationRelease
http://sap.fusesource.org/idoc/MY_REPO/FLCUSTOMER_CREATEFROMDATA01///
<convertBodyTo type="java.lang.String"/>
<convertBodyTo type="org.fusesource.camel.component.sap.model.idoc.Document"/>
<?xml version="1.0" encoding="ASCII"?> <idoc:Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:FLCUSTOMER_CREATEFROMDATA01---="http://sap.fusesource.org/idoc/XXX/FLCUSTOMER_CREATEFROMDATA01///" xmlns:idoc="http://sap.fusesource.org/idoc" creationDate="2015-01-28T12:39:13.980-0500" creationTime="2015-01-28T12:39:13.980-0500" iDocType="FLCUSTOMER_CREATEFROMDATA01" iDocTypeExtension="" messageType="FLCUSTOMER_CREATEFROMDATA" recipientPartnerNumber="QUICKCLNT" recipientPartnerType="LS" senderPartnerNumber="QUICKSTART" senderPartnerType="LS"> <rootSegment xsi:type="FLCUSTOMER_CREATEFROMDATA01---:ROOT" document="/"> <segmentChildren parent="//@rootSegment"> <E1SCU_CRE parent="//@rootSegment" document="/"> <segmentChildren parent="//@rootSegment/@segmentChildren/@E1SCU_CRE.0"> <E1BPSCUNEW parent="//@rootSegment/@segmentChildren/@E1SCU_CRE.0" document="/" CUSTNAME="Fred Flintstone" FORM="Mr." STREET="123 Rubble Lane" POSTCODE="01234" CITY="Bedrock" COUNTR="US" PHONE="800-555-1212" EMAIL="fred@bedrock.com" CUSTTYPE="P" DISCOUNT="005" LANGU="E"/> </segmentChildren> </E1SCU_CRE> </segmentChildren> </rootSegment> </idoc:Document>
from("direct:getFlightCustomerInfo") .to("bean:createFlightCustomerGetListRequest") .to("sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST") .to("bean:returnFlightCustomerInfo");
<route> <from uri="direct:getFlightCustomerInfo"/> <to uri="bean:createFlightCustomerGetListRequest"/> <to uri="sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST"/> <to uri="bean:returnFlightCustomerInfo"/> </route>
public void create(Exchange exchange) throws Exception { // Get SAP Endpoint to be called from context. SapSynchronousRfcDestinationEndpoint endpoint = exchange.getContext().getEndpoint("sap-srfc-destination:nplDest:BAPI_FLCUST_GETLIST", SapSynchronousRfcDestinationEndpoint.class); // Retrieve bean from message containing Flight Customer name to // look up. BookFlightRequest bookFlightRequest = exchange.getIn().getBody(BookFlightRequest.class); // Create SAP Request object from target endpoint. Structure request = endpoint.getRequest(); // Add Customer Name to request if set if (bookFlightRequest.getCustomerName() != null && bookFlightRequest.getCustomerName().length() > 0) { request.put("CUSTOMER_NAME", bookFlightRequest.getCustomerName()); } } else { throw new Exception("No Customer Name"); } // Put request object into body of exchange message. exchange.getIn().setBody(request); }
public void createFlightCustomerInfo(Exchange exchange) throws Exception { // Retrieve SAP response object from body of exchange message. Structure flightCustomerGetListResponse = exchange.getIn().getBody(Structure.class); if (flightCustomerGetListResponse == null) { throw new Exception("No Flight Customer Get List Response"); } // Check BAPI return parameter for errors @SuppressWarnings("unchecked") Table<Structure> bapiReturn = flightCustomerGetListResponse.get("RETURN", Table.class); Structure bapiReturnEntry = bapiReturn.get(0); if (bapiReturnEntry.get("TYPE", String.class) != "S") { String message = bapiReturnEntry.get("MESSAGE", String.class); throw new Exception("BAPI call failed: " + message); } // Get customer list table from response object. @SuppressWarnings("unchecked") Table<? extends Structure> customerList = flightCustomerGetListResponse.get("CUSTOMER_LIST", Table.class); if (customerList == null || customerList.size() == 0) { throw new Exception("No Customer Info."); } // Get Flight Customer data from first row of table. Structure customer = customerList.get(0); // Create bean to hold Flight Customer data. FlightCustomerInfo flightCustomerInfo = new FlightCustomerInfo(); // Get customer id from Flight Customer data and add to bean. String customerId = customer.get("CUSTOMERID", String.class); if (customerId != null) { flightCustomerInfo.setCustomerNumber(customerId); } // Put bean into body of exchange message. exchange.getIn().setHeader("flightCustomerInfo", flightCustomerInfo); }
from("direct:createFlightTrip") .to("bean:createFlightTripRequest") .to("sap-srfc-destination:nplDest:BAPI_FLTRIP_CREATE?transacted=true") .to("bean:returnFlightTripResponse");
<route> <from uri="direct:createFlightTrip"/> <to uri="bean:createFlightTripRequest"/> <to uri="sap-srfc-destination:nplDest:BAPI_FLTRIP_CREATE?transacted=true"/> <to uri="bean:returnFlightTripResponse"/> </route>
DataFormat jaxb = new JaxbDataFormat("org.fusesource.sap.example.jaxb"); from("sap-srfc-server:nplserver:BOOK_FLIGHT") .unmarshal(jaxb) .multicast() .to("direct:getFlightConnectionInfo", "direct:getFlightCustomerInfo", "direct:getPassengerInfo") .end() .to("direct:createFlightTrip") .marshal(jaxb);
<route> <from uri="sap-srfc-server:nplserver:BOOK_FLIGHT"/> <unmarshal> <jaxb contextPath="org.fusesource.sap.example.jaxb"/> </unmarshal> <multicast> <to uri="direct:getFlightConnectionInfo"/> <to uri="direct:getFlightCustomerInfo"/> <to uri="direct:getPassengerInfo"/> </multicast> <to uri="direct:createFlightTrip"/> <marshal> <jaxb contextPath="org.fusesource.sap.example.jaxb"/> </marshal> </route>
@XmlRootElement(name="Request", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class BookFlightRequest { @XmlAttribute(name="CUSTNAME") private String customerName; @XmlAttribute(name="FLIGHTDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date flightDate; @XmlAttribute(name="TRAVELAGENCYNUMBER") private String travelAgencyNumber; @XmlAttribute(name="DESTINATION_FROM") private String startAirportCode; @XmlAttribute(name="DESTINATION_TO") private String endAirportCode; @XmlAttribute(name="PASSFORM") private String passengerFormOfAddress; @XmlAttribute(name="PASSNAME") private String passengerName; @XmlAttribute(name="PASSBIRTH") @XmlJavaTypeAdapter(DateAdapter.class) private Date passengerDateOfBirth; @XmlAttribute(name="CLASS") private String flightClass; }
@XmlRootElement(name="Response", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class BookFlightResponse { @XmlAttribute(name="TRIPNUMBER") private String tripNumber; @XmlAttribute(name="TICKET_PRICE") private BigDecimal ticketPrice; @XmlAttribute(name="TICKET_TAX") private BigDecimal ticketTax; @XmlAttribute(name="CURRENCY") private String currency; @XmlAttribute(name="PASSFORM") private String passengerFormOfAddress; @XmlAttribute(name="PASSNAME") private String passengerName; @XmlAttribute(name="PASSBIRTH") @XmlJavaTypeAdapter(DateAdapter.class) private Date passengerDateOfBirth; @XmlElement(name="FLTINFO") private FlightInfo flightInfo; @XmlElement(name="CONNINFO") private ConnectionInfoTable connectionInfo; }
@XmlRootElement(name="FLTINFO", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class FlightInfo { @XmlAttribute(name="FLIGHTTIME") private String flightTime; @XmlAttribute(name="CITYFROM") private String cityFrom; @XmlAttribute(name="DEPDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date departureDate; @XmlAttribute(name="DEPTIME") @XmlJavaTypeAdapter(DateAdapter.class) private Date departureTime; @XmlAttribute(name="CITYTO") private String cityTo; @XmlAttribute(name="ARRDATE") @XmlJavaTypeAdapter(DateAdapter.class) private Date arrivalDate; @XmlAttribute(name="ARRTIME") @XmlJavaTypeAdapter(DateAdapter.class) private Date arrivalTime; }
@XmlRootElement(name="CONNINFO_TABLE", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class ConnectionInfoTable { @XmlElement(name="row") List<ConnectionInfo> rows; }
@XmlRootElement(name="CONNINFO", namespace="http://sap.fusesource.org/rfc/nplServer/BOOK_FLIGHT") @XmlAccessorType(XmlAccessType.FIELD) public class ConnectionInfo { @XmlAttribute(name="CONNID") String connectionId; @XmlAttribute(name="AIRLINE") String airline; @XmlAttribute(name="PLANETYPE") String planeType; @XmlAttribute(name="CITYFROM") String cityFrom; @XmlAttribute(name="DEPDATE") @XmlJavaTypeAdapter(DateAdapter.class) Date departureDate; @XmlAttribute(name="DEPTIME") @XmlJavaTypeAdapter(DateAdapter.class) Date departureTime; @XmlAttribute(name="CITYTO") String cityTo; @XmlAttribute(name="ARRDATE") @XmlJavaTypeAdapter(DateAdapter.class) Date arrivalDate; @XmlAttribute(name="ARRTIME") @XmlJavaTypeAdapter(DateAdapter.class) Date arrivalTime; }