1. Dennis Little
  2. PowerBuilder
  3. Thursday, 28 February 2019 19:27 PM UTC

Hi all,

We're doing some integration to SalesForce.  We're on PB 2017 R3.  So we have an application that needs to upload several xls/pdf files to SalesForce.

I know there are some API calls to be made.  We have a meeting next week in regards to the specific API needed.

 

Has anyone used the SalesForce API to upload files form PB?  If so, do you have any examples available?

 

Thanks,

Dennis L

Dennis Little Accepted Answer Pending Moderation
  1. Tuesday, 19 March 2019 18:45 PM UTC
  2. PowerBuilder
  3. # 1

Kevin, So my SF guy is back from vacation.

I'm trying to convert the java example to PB.  I'm having trouble figuring out how to set this up, as far as the redirecturi fits into the PB call.  Is the redirect something I need to set up locally?  Am I calling it correctly in PB?

 

Thanks

Dennis

Here is the Java:
/*
01 initParams = {
02 @WebInitParam(name = "clientId", value = "3MVG9lKcPoNINVBJSoQsNCD"),
04 @WebInitParam(name = "clientSecret", value = "5678471853609579508"),
05 @WebInitParam(name = "redirectUri", value =
06 "https://localhost:8443/RestTest/oauth/_callback"),
07 @WebInitParam(name = "environment", value =
08 "https://login.salesforce.com/services/oauth2/token") }
09
10 HttpClient httpclient = new HttpClient();
11 PostMethod post = new PostMethod(environment);
12 post.addParameter("code",code);
13 post.addParameter("grant_type","authorization_code");
14
15 /** For session ID instead of OAuth 2.0, use "grant_type", "password" **/
16 post.addParameter("client_id",clientId);
17 post.addParameter("client_secret",clientSecret);
18 post.addParameter("redirect_uri",redirectUri);
*/

------------------------------------------------------------------------------------------------------------------------------------

Here is my PB code:

integer rc
oauthclient client
tokenrequest request
tokenresponse response
string accesstoken


request.clientid = 'xxxxxxxxxxxxxxxxxxxxxx'
request.clientsecret = 'xxxxxxxxxxxxxxxxxx'
request.granttype = 'client_credentials'
request.method = 'POST'
request.setheader('redirectUri', 'https://localhost:8443/RestTest/oauth/_callback')
request.tokenlocation = "https://xxxxxx.salesforce.com/services/oauth2/token"

client = create oauthclient
rc = client.accesstoken(request, response)
destroy client

accesstoken = response.getaccesstoken()

Comment
  1. Kevin Ridley
  2. Thursday, 21 March 2019 11:29 AM UTC
It should be client_credentials, but I have also done it using granttype password as well.
  1. Helpful
  1. Dennis Little
  2. Thursday, 21 March 2019 12:10 PM UTC
Kevin, can you send me the example code that you used? I can't mine to return anything. Thanks
  1. Helpful
  1. Kevin Ridley
  2. Thursday, 21 March 2019 14:29 PM UTC
I'll post here since there were others asking for similar OAuth2 code and I haven't had a chance to post my presentation to CodeXchage yet. This isn't working because I need more info from SF about what parameters are needed but it's close. It at least gives you a good error. Maybe you can try the request.username and request.password parameters and use granttype password.



integer li_rc

oauthclient lo_client

tokenrequest request

tokenresponse response

string ls_accesstoken, ls_type, ls_desc, ls_uri, ls_state



try

request.SetHeader ( "User-Agent", "Appeon test" )

request.clientid = '3MVG9lKcPoNINVBJSoQsNCD'

request.clientsecret = '5678471853609579508'

request.granttype = 'client_credentials'

request.method = 'POST'

request.setheader('redirectUri', 'https://localhost')

// request.tokenlocation = "https://login.salesforce.com/services/oauth2/authorize"

request.tokenlocation = "https://login.salesforce.com/services/oauth2/token"



lo_client = create oauthclient

li_rc = lo_client.accesstoken(request, response)

IF li_rc = 1 AND response.getstatuscode() = 200 THEN

ls_accesstoken = response.getaccesstoken()

mle_response.text = ls_accesstoken

ELSE

response.gettokenerror(ls_type, ls_desc, ls_uri, ls_state)

mle_response.text = String(response.getstatuscode()) + ": " + ls_type + " - " + ls_desc

END IF

catch(runtimeerror re)

MessageBox("RuntimeError", re.getmessage())

finally

IF IsValid(lo_client) THEN

destroy lo_client

END IF

end try
  1. Helpful
There are no comments made yet.
Dennis Little Accepted Answer Pending Moderation
  1. Tuesday, 12 March 2019 17:38 PM UTC
  2. PowerBuilder
  3. # 2

Thanks Kevin,

I get that I need to convert from Base64 to Json.  I guess I just assumed that while converting to base64 seemed pretty standard, as in only 1 version of base64,  whereas json seems to be more flexible.  I thought I saw an example on the SalesForce website.

After getting deeper into Bruce's presentation, I see where he uses the OAuthclient to make the call when requesting the resource token.

Like you suggested, it looks like that's the way to go, 1-Get the token, 2- File conversion, 3-Pass it along with the resource token.

I searched for your presentation, but couldn't locate it.  I'd like to work thru it as well.  Any idea where it might be, or what the title is?

Thanks again Kevin

 

Dennis

 

Comment
  1. Kevin Ridley
  2. Tuesday, 12 March 2019 19:59 PM UTC
Hey Dennis,

I tried to find the presentation, but all I could find was the title and small writeup:

PowerBuilder CRUD Operations on Dynamics 365 Entities

Learn how to do full CRUD operations from PowerBuilder to access and manipulate data in Dynamics 365 data using ODBC, OData, or REST interfaces. Topics covered include: how to set up and manage connections for the 3 interfaces; how to securely perform CRUD operations over Dynamics 365 Web APIs; how to display the before and after data.



I know I have to code at home along with the powerpoint. The challenge is going to figure out how to get it to you.
  1. Helpful
There are no comments made yet.
Kevin Ridley Accepted Answer Pending Moderation
  1. Tuesday, 12 March 2019 15:58 PM UTC
  2. PowerBuilder
  3. # 3

Hi Dennis,

 Thought I replied to this yesterday, but I don't see it so I'll try again.  I think some of what you are struggling with is your statement "You'd think that if I'm converting a file to base64, that the resulting json would be pretty standard".  When you convert the file to base64, the result is NOT JSON.  The result is a Base64 string/blob.  Chances are you probably need to have that string be a value in a JSON string of name/value pairs most likely.  You will need to build a JSON string using the JSONGenerator object, or you can just build a JSON string manually if you want.  Think of JSON as the "new" xml.  It's very similar in functionality but quickly becoming the new industry standard.  That's why it's going to be important that your contact from SF gets you a sample of the JSON they will be expecting so you can figure out how to match it.  You're going to also find it helpful if they can supply a full sample request, once you get further along.  I suggest you download a tool called Fiddler which is great for troubleshooting web service calls.  SoapUI is another tool that now has REST support and can be useful.

 

If it was me, I'd do the connection first to make sure I can even access the REST services, then work on creating the request (formatting etc).  1 important thing to know is, you can use the OAuthClient object to actually make the REST service call, you don't need to use the HTTPClient.  You can do everything the HTTPClient does and more with the OauthClient, so you don't need to mix and match.  For my presentation I did everything using the OAuthClient.

 

Good luck,

KR

Comment
There are no comments made yet.
Dennis Little Accepted Answer Pending Moderation
  1. Monday, 11 March 2019 19:17 PM UTC
  2. PowerBuilder
  3. # 4

Kevin,

Thanks for the info.  As far as the OAuth goes, Bruce has a pretty nice OAuth/rest/httpclient demo I'm working thru now.  Of course, my SF contact is on vacation this week.

Anyway, I do have a question concerning json.  You'd think that if I'm converting a file to base64, that the resulting json would be pretty standard.  I'm kind of trying to tackle the base64/json issue first then connect to SF.  Seems like a pretty complicated way to upload a file.

I'll try to locate your elevate session and work thru it as well.

Anyway, I'm trying to figure it out myself, but if I need to get outside the box, I'll certainly be in contact.

Thanks
Dennis

 

Comment
There are no comments made yet.
Kevin Ridley Accepted Answer Pending Moderation
  1. Monday, 11 March 2019 15:58 PM UTC
  2. PowerBuilder
  3. # 5

I took a quick look at the link you sent and you might want to start here:

https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/quickstart.htm

 

It sounds like you will first need to create a connection using OAuth which may end up being as hard or harder than uploading the file ;-).  It's similar in functionality to my Elevate presentation where I used OAuth to connect to MS Dynamics and then use their REST API to perform CRUD operations on the Dynamics entities.  I'm not sure if it's listed here under the Elevate 2018 presentations or not.  I'm sure I could scrape up the code.

 

Anyway, the first step is to get your PB app connecting to Salesforce.  Hopefully they will have a service account you can setup.  Then you use the service account to request a token which you use for each request in your session.  You will use the OAuth client object to do this (after setting up the service account).  You are correct that you will need to build the JSON, not parse it.  The JSONParser is used if you get a JSON response.  You can use the JSONGenerator to build the JSON for your request (or even build it manually, it's just a string).  SalesForce or someone in the SF Community should be able to supply you with a sample request so you'll know what to build. 

 

If you decide it's too much and want to outsource this, lmk, I can supply my contact info.

 

Kevin

Comment
There are no comments made yet.
Dennis Little Accepted Answer Pending Moderation
  1. Friday, 8 March 2019 20:52 PM UTC
  2. PowerBuilder
  3. # 6

Kevin,

I do not have an example of the expected json.  It sounds like I need to generate the json, not parse it.

SalesForce Chatter API - Here is a link to what I'm trying to do.  Do you have an example of converting to json?

 

Thanks

Dennis

 

Comment
There are no comments made yet.
Kevin Ridley Accepted Answer Pending Moderation
  1. Friday, 8 March 2019 20:36 PM UTC
  2. PowerBuilder
  3. # 7

Dennis,

 Do you have an example of what the JSON is supposed to look like?  I suspect that you are getting that error because the string you are trying to load is supposed to be in JSON format and it's not, it's just the encoded string from the base64encode function of the coder object.  I think you'll need to build a JSON string and the string you currently have will be the value of one of the JSON attributes.  Please provide what the API is looking for, or sample JSON that the service expects.

Comment
There are no comments made yet.
Dennis Little Accepted Answer Pending Moderation
  1. Friday, 8 March 2019 19:40 PM UTC
  2. PowerBuilder
  3. # 8

Armeen,

Thanks for the links, very helpful.  I just got off the conf call with the SalesForce guys and it is pretty much how you laid it out.

I'm working thru Bruce's presentation now.

I have a question about the json parser.  I have a pdf file that I'm converting to a blob and then to base 64.  After I run it thru the jsonparser,  I get Invalid value. as my json value.

Any help would be appreciated.

 

/*File to blob*/
integer li_file
long ll_bytes, ll_root, ll_count
blob lb_file
boolean lb_exist
string ls_base64, ls_json
coderobject lnv_coder
jsonparser json

string ls_filename = 'C:\download\chatter1.pdf'

lb_exist = fileexists(ls_filename)
if lb_exist then
li_file = fileopen(ls_filename, streammode!)
ll_bytes = filereadex(li_file, lb_file)

/*Blob to base64*/
lnv_coder = create coderobject
ls_base64 = lnv_coder.base64encode(lb_file)
end if

messagebox('ls_base64', left(ls_base64, 30))//I get nice long string here

json = create jsonparser
ls_json = json.loadstring(ls_base64)

if ls_json = 'Invalid value.' then
messagebox('ls_json', 'Invalid value.')
end if

 

Comment
There are no comments made yet.
Armeen Mazda @Appeon Accepted Answer Pending Moderation
  1. Thursday, 28 February 2019 22:28 PM UTC
  2. PowerBuilder
  3. # 9

Sorry, don't have any examples.  But most likely SalesForce APIs are REST.

So just point out few new features of PB 2017 R3 that you may need to call SalesForce APIs:

  1. - CoderObject object (to Base64 encode/decode binary files)
  2. - JSONParser/Generator object (to parse/generate JSON data)
  3. - OAuthClient object (to provide access token to the REST API for authentication)
  4. - HTTPClient object (to execute the actual REST call using TLS 1.2)

Bruce Armstrong has made some really good presentations about this stuff at last year's PowerBuilder conference: 

Comment
  1. Kevin Ridley
  2. Friday, 1 March 2019 17:51 PM UTC
JSONPackage object is quite useful also for working with JSON for REST services.
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.