Thursday, April 30, 2015

Integration Series 1 Use Case 1 - SalesForce to SAP

In the Integration Series 1 Overview, Luis Cortes (@licortes_redhat) described the integration series and the 4 use cases that we will be showing.  As you can see in the diagram to the right the integration series shows how to use Fuse as the integration platform to bridge Salesforce-SAP-Feedhenry.

Overview

It is a common scenario in enterprise customers that records of potential customers (aka prospects) are not a part of the customer database used by other applications (such as ERPs) until they become customers.

The first Use Case that we will explore is Salesforce to SAP.  When an opportunity is closed in Salesforce then a customer record is created in SAP. 


 The flow of the use case is:
  1. View the web browser with SalesForce page with info on the opportunity “Acme Consulting”.
  2. View the web browser with SAP customers screen, we search for “Acme consulting”, it dos not appear there.
  3. Back to the browser.
  4. Click on the dropdown “Stage” and change it to “Closed win”
  5. Submit
  6. Now SalesForce page shows “Acme Consulting” opportunity with stage as “Closed Win”
  7. Show web browser with SAP customers, we search for “Acme consulting”, it appears there with the info from SalesForce
The Opportunity Salesforce screen:


The SAP Customer Search screen in SAP GUI Console:



Requirements

In order to use the test code to run the use case you must have completed the simple demos with the components in order to have the accounts and server side setup correctly.  The Salesforce Component and SAP JCo Components will be used with Use Case 1.
The Project for Use Case 1

First import the first use case into JBDS.  Let's take a look at the pom.xml which will contain the dependencies for the Salesforce and SAP JCo Components.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany</groupId>
  <artifactId>camel-spring</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0-SNAPSHOT</version>

  <name>A Camel Spring Route</name>
  <url>http://www.myorganization.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  </properties>

  <repositories>
    <repository>
      <id>release.fusesource.org</id>
      <name>FuseSource Release Repository</name>
      <url>http://repo.fusesource.com/nexus/content/repositories/fs-releases</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
    <repository>
     <id>ea.fusesource.org</id>
     <name>FuseSource Community Early Access Release Repository</name>
     <url>http://repo.fusesource.com/nexus/content/groups/ea</url>
     <snapshots>
      <enabled>false</enabled>
     </snapshots>
     <releases>
      <enabled>true</enabled>
     </releases>
    </repository>    
    <repository>
      <id>snapshot.fusesource.org</id>
      <name>FuseSource Snapshot Repository</name>
      <url>http://repo.fusesource.com/nexus/content/repositories/snapshots</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>false</enabled>
      </releases>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>release.fusesource.org</id>
      <name>FuseSource Release Repository</name>
      <url>http://repo.fusesource.com/nexus/content/repositories/releases</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <enabled>true</enabled>
      </releases>
    </pluginRepository>
    <pluginRepository>
     <id>ea.fusesource.org</id>
     <name>FuseSource Community Early Access Release Repository</name>
     <url>http://repo.fusesource.com/nexus/content/groups/ea</url>
     <snapshots>
      <enabled>false</enabled>
     </snapshots>
     <releases>
      <enabled>true</enabled>
     </releases>
    </pluginRepository>      
    <pluginRepository>
      <id>snapshot.fusesource.org</id>
      <name>FuseSource Snapshot Repository</name>
      <url>http://repo.fusesource.com/nexus/content/repositories/snapshots</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>false</enabled>
      </releases>
    </pluginRepository>
  </pluginRepositories>

  <dependencies>
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-core</artifactId>
      <version>2.12.0.redhat-610394</version>
    </dependency>
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-spring</artifactId>
      <version>2.12.0.redhat-610394</version>
    </dependency>
    
    <!-- camel-salesforce -->
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-salesforce</artifactId>
      <version>2.12.0.redhat-610394</version>
    </dependency>

<dependency>               
 <groupId>com.sap.conn.jco</groupId>              
 <artifactId>sapjco3</artifactId>              
 <version>3.0.11</version>              
 <scope>system</scope>              
 <systemPath>/home/kpeeples/sapjco3/sapjco3.jar</systemPath>        
 </dependency>   
<dependency>          
 <groupId>org.fusesource</groupId>          
 <artifactId>camel-sap</artifactId>         
 <version>1.0.0.redhat-379</version>         
 <exclusions>                
  <exclusion>                      
   <groupId>com.sap.conn.jco</groupId>
              <artifactId>sapjco3</artifactId>
   </exclusion>             
  </exclusions>        
</dependency>

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-xmljson</artifactId>
  <version>2.12.0.redhat-610394</version>
  <!-- Use the same version as camel-core, but remember that this component is only available from 2.10 onwards -->
</dependency>
 

    <!-- logging -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.5</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.5</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

    <!-- testing -->
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-test-spring</artifactId>
      <version>2.12.0.redhat-610394</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

  <build>
    <defaultGoal>install</defaultGoal>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>

      <!-- allows the route to be ran via 'mvn camel:run' -->
      <plugin>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-maven-plugin</artifactId>
        <version>2.12.0.redhat-610379</version>
      </plugin>
      
            <!-- camel -->
      <plugin>
        <groupId>org.apache.camel.maven</groupId>
        <artifactId>camel-salesforce-maven-plugin</artifactId>
        <version>2.12.0.redhat-610394</version>
      </plugin>
      
    </plugins>
  </build>

</project>

Now we will examine the Camel-Context.xml.

First we are setting up the requirements for Salesforce and then the requirements for SAP.  We subscribe to the CamelTest Topic to listen for changes to Opportunity Objects.  Any that have been modified to 'Closed Won'  then create the Customer from the Opportunity Name (in the future we could grab the Account Name) in SAP.  Then we grab the customer list back from SAP and can verify the customer was created.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
 <bean
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location">
   <value>classpath:salesforce.properties</value>
  </property>
 </bean>
 <bean id="salesforce"
  class="org.apache.camel.component.salesforce.SalesforceComponent">

  <property name="loginConfig">
   <bean class="org.apache.camel.component.salesforce.SalesforceLoginConfig">
    <property name="loginUrl" value="${loginUrl}"></property>
    <property name="userName" value="${userName}"></property>
    <property name="password" value="${password}"></property>
    <property name="clientId" value="${clientId}"></property>
    <property name="clientSecret" value="${clientSecret}"></property>
   </bean>
  </property>
  <property name="config">
   <bean
    class="org.apache.camel.component.salesforce.SalesforceEndpointConfig">
    <property name="sObjectName" value="${sObjectName}"></property>
    <property name="sObjectClass" value="${sObjectClass}"></property>
   </bean>
  </property>
  <property name="packages" value="${sObjectDTOPackages}"></property>
 </bean>
   <bean id="sap" class="org.fusesource.camel.component.sap.SAPComponent">
   <property name="destinationDataStore">
    <map>
     <entry key="NPL" value-ref="nplDestinationData" />
    </map>
   </property>
   <property name="serverDataStore">
    <map />
   </property>
   <property name="repositoryDataStore">
    <map />
   </property>
  </bean>

  <bean id="nplDestinationData" class="org.fusesource.camel.component.sap.model.rfc.impl.DestinationDataImpl">
   <property name="ashost" value="nplhost1" />
   <property name="sysnr" value="00" />
   <property name="client" value="001" />
   <property name="user" value="developer" />
   <property name="passwd" value="password" />
   <property name="lang" value="en" />
  </bean>
  

 <camelContext xmlns="http://camel.apache.org/schema/spring">
 
 <dataFormats>
     <xmljson id="xmljson"/>
     <xmljson id="xmljsonWithOptions" forceTopLevelObject="true" trimSpaces="true" rootName="newRoot" skipNamespaces="true" 
             removeNamespacePrefixes="true" expandableProperties="d e"/>
 </dataFormats>
 
    <route id="sfRoute">
        <!--   from uri="timer://foo?repeatCount=0"/> -->
        <from uri="salesforce:CamelTest?notifyForFields=ALL&amp;notifyForOperations=ALL&amp;sObjectName=Opportunity&amp;updateTopic=true&amp;sObjectQuery=SELECT Id, Name, StageName, AccountId FROM Opportunity"/>
        <convertBodyTo type="java.lang.String"/>
        <unmarshal ref="xmljson"/>
        <log message="Query result back from Salesforce: ${body}"/>
  <choice>
            <when>
                <xpath>/o/StageName='Closed Won'</xpath>
                <to uri="sap:destination:NPL:BAPI_FLCUST_CREATEFROMDATA?transacted=true" />
         <to uri="sap:destination:NPL:BAPI_FLCUST_GETLIST" />
   <to uri="log:sapintegration?level=INFO" />
   <to uri="file:target?fileName=BAPI_FLCUST_GETLIST.xml" />
            </when>
            <otherwise>
                <to uri="log:otherwise display" />
            </otherwise>
        </choice>
    </route>
</camelContext>
</beans>

The properties used for salesforce are in the salesforce.properties file while the properties for SAP are in the camel-context.xml.

1
2
3
4
5
6
7
8
loginUrl=https://login.salesforce.com
clientId=
clientSecret=
userName=kennethwpeeples@redhat.com
password=
sObjectDTOPackages=org/apache/camel/salesforce/dto
sObjectName=Opportunity
sObjectClass=org.apache.camel.salesforce.dto.Opportunity.class

Running the Use Case Code

Step 1 - Download the Project from JBoss Demo Central - https://github.com/jbossdemocentral/fh-fuse-sap-sf-integration-demo

Step 2 - Import into JBDS

Step 3 - Right click on the Camel Context in the uc1 Project and run as Camel Context without tests

Step 4 - Create the ACME Consulting Opportunity and change the stage to Closed Win

Step 5 - Submit 

Step 6 - Look at the console window

Step 7 - The route will show the Closed Opportunity is picked up and the customer is created in SAP.

Step 8 - The route will also show the search of the opportunity and it is displayed in the log

Step 9 - Verify through the SAP GUI console that the Customer is created

Presentation:


Video:

 

References

Series References

Integration Series 1 (This article) - Overview from Luis Cortes
Integration Series 1 Use Case 1 - SalesForce to SAP 
Integration Series 1 Use Case 2 - Mobile to SalesForce to SAP
Integration Series 1 Use Case 3 - SAP to SalersForce 
Integration Series 1 Use Case 4 - SAP to Mobile to SalesForce