One of the great aspects of ThingWorx is the ability to connect disparate data silos to a central IoT hub. Many of these silos are made accessible through Web APIs. RESTful Web APIs enable developers to pull data from an inexhaustible number of sources around the web; often using nothing but a HTTP URI. Salesforce has an extensive REST API that can be accessed through ThingWorx. This blog will introduce you to creating a “Connected App” on Salesforce, authentication using username and password in ThingWorx, adding records to Salesforce, and finally modifying records. For a detailed description of Salesforce’s REST API, visit https://developer.salesforce.com/page/REST_API

Step 1 (Optional): Obtain a Developer Environment with Salesforce.com

If you do not already have a Salesforce account, navigate to https://developer.salesforce.com/platform/force.com and sign up for a free developer environment. It only takes a few minutes and you get a fully functioning Salesforce instance that you can freely develop in.

Step 2: Obtain a Security Token

You’ll need a security token to authenticate with a username and password. If you don’t already have one, or can’t dig it up from previous emails, you’ll need to reset the token.

Resetting the Token

1.    In the upper right-hand corner of your Salesforce page, click on your name and select “My Settings”

2.    On the left-hand menu, select “Personal”

3.    Under “Personal,” select “Reset My Security Token”

4.    Follow the directions on the page and you will receive a new security token via email

Step 3: Create a Connected App

To use the REST API, we’ll need to create a connected app that gives us a “Consumer Key” and a “Consumer Secret”.

Creating the Connected App

1.    Click on “Settings” in the upper right of your Salesforce screen

2.    On the left side, navigate to “Build” > “Create” > “Apps”

3.    Under the “Connected Apps” section, select “New”

4.    Fill out the fields as shown below. A callback URL is required but we won’t really be referencing it anywhere in ThingWorx. There is a great article on using Postman to test out REST calls with Salesforce at https://blog.mkorman.uk/using-postman-to-explore-salesforce-restful-web-services/ . The callback URL is used in the examples when authenticating in Postman.

5.    Click “Save.” You will get an alert that your connected app will take 2-10 minutes to take effect.

6.    After you click “Save,” you’ll see the “Consumer Key” and “Consumer Secret.” Copy those somewhere to use in ThingWorx.

Step 4: Authenticate Salesforce Session in ThingWorx

In this step, we’ll create a service in ThingWorx that returns a JSON for us to use in our other Salesforce requests.

1.    Create a service inside your Thing called AuthenticateSalesForce. I have a “TestThing” that I’ve created where I can try out new services without disrupting any of my live projects.

2.    Choose the “STRING” type for the result output, no inputs are needed unless you want to have the end user input their username and password. After we test functionality, we’ll change the output type to “JSON”

3.    Enter the following code, which is just the POST JSON function in the ContentLoaderFunction resource.

var params = {

                 proxyScheme: undefined /* STRING */,
                 headers: undefined /* JSON */,
                 ignoreSSLErrors: undefined /* BOOLEAN */,
                 useNTLM: undefined /* BOOLEAN *
                 workstation: undefined /* STRING */,
                 useProxy: undefined /* BOOLEAN */,
                 withCookies: undefined /* BOOLEAN */,
                 proxyHost: undefined /* STRING */,

url: "https://login.salesforce.com/services/oauth2/token?grant_type=password&client_id=&client_secret=&username= &password=" /* STRING */,

                 content: undefined /* JSON */,
                 timeout: undefined /* NUMBER */,
                 proxyPort: undefined /* INTEGER */,
                 password: undefined /* STRING */,
                 domain: undefined /* STRING */,
                 username: undefined /* STRING */

};

// result: JSON
var j = Resources["ContentLoaderFunctions"].PostJSON(params);

var result = j.access_token;

4.    Enter the consumer key, consumer secret, username (use %40 for the ‘@’ symbol), and password plus security token (enter your password and security token with no spaces between the two)

5.    Select “Done” on your service, save your Thing, and test the service. You should receive a session token like the one seen below:

6.    If nothing shows up, either the Salesforce server hasn’t activated the app, or there may be an issue with the URL. If you copy and paste the URL into PostMan, you should get an error message that clarifies the issue.

7.    When you’re getting an access token as the result, edit your service, change the result type to “JSON,” delete the last line (the “var result = j.access_token” line”), and modify the end of the service to now read:

// result: JSON

var result = Resources[“ContentLoaderFunctions”].PostJSON(params);

Step 5: Create a record in Salesforce

In this step, we’ll create a new account within salesforce using our new authentication service and a REST call utilizing the ContentLoaderFunctions.

1.    Create another new service in your Thing and call it AddSalesForceAccount. 2.    Create an input and call it AccountName. The type is “STRING” 3.    Type in the following code:

var authJSON = me.AuthenticateSalesForce();

var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var url = instance_url + "/services/data/v20.0/sobjects/Account/";

var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};

var content = {
 "Name" : AccountName
};

var params = {
                 proxyScheme: undefined /* STRING */,
                 headers: headers /* JSON */,
                 ignoreSSLErrors: undefined /* BOOLEAN */,
                 useNTLM: undefined /* BOOLEAN */,
                 workstation: undefined /* STRING */,
                 useProxy: undefined /* BOOLEAN */,
                 withCookies: undefined /* BOOLEAN */,
                 proxyHost: undefined /* STRING */,
   url: url /* STRING */,
                 content: content /* JSON */,
                 timeout: undefined /* NUMBER */,
                 proxyPort: undefined /* INTEGER */,
                 password: undefined /* STRING */,
                 domain: undefined /* STRING */,
                 username: undefined /* STRING */
};

// result: JSON
var result = Resources["ContentLoaderFunctions"].PostJSON(params);

4. Test the service. Enter a unique account name and verify that it shows up in Salesforce.

Step 6: Retrieve a Record ID

To modify a record, the record ID must be used to reference the object of interest. We can make a request to Salesforce to return relevant records using an SOQL query. This example will cover retrieving the record ID of the account we just created in the last step.

1.    Create a new service in your Thing

2.    Create an input and call it AccountName. The type is “STRING”

3.    Type in the following code:

var authJSON = me.AuthenticateSalesForce();


var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var url = instance_url + "/services/data/v20.0/query/?q=SELECT+name+FROM+Account+WHERE+name+=+'" + AccountName + "'";

var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};




var params = {
                  proxyScheme: undefined /* STRING */,
                  headers: headers /* JSON */,
                  ignoreSSLErrors: undefined /* BOOLEAN */,
                  useNTLM: undefined /* BOOLEAN */,
                  workstation: undefined /* STRING */,
                  useProxy: undefined /* BOOLEAN */,
                  withCookies: undefined /* BOOLEAN */,
                  proxyHost: undefined /* STRING */,
                  url: url /* STRING */,
                  timeout: undefined /* NUMBER */,
                  proxyPort: undefined /* INTEGER */,
                  password: undefined /* STRING */,
                  domain: undefined /* STRING */,
                  username: undefined /* STRING */

};




// result: JSON
var j = Resources["ContentLoaderFunctions"].GetJSON(params);

var result = j.records[0].attributes.url;

4. Give the service a name and test it. The output of this service is a url that can be appended to the instance_url that is returned in the response from the Authentication service.

Step 7: Modify a Record

Using the output from our last service, we can now easily modify the fields of the record ID that we just retrieved. Keep in mind, if you create a custom field and you want to modify its value, add a “__c” to the end of the field name (denotes custom field).

  1. Create a new service in your Thing
  2. Let’s give it a few “STRING” inputs: field, stringValue, and AccountName
  3. Input the following code:
var authJSON = me.AuthenticateSalesForce();

var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var stringJSON = '{"' + field + '":' + stringValue + "}";


var params = {
                  AccountName: AccountName /* STRING */
};

// result: STRING
var object_url = me.RetrieveSalesForceAccountRecordID(params);

var url = instance_url + object_url + "?_HttpMethod=PATCH";
var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};

var content = JSON.parse(stringJSON);

var params = {
                  proxyScheme: undefined /* STRING */,
                  headers: headers /* JSON */,
                  ignoreSSLErrors: undefined /* BOOLEAN */,
                  useNTLM: undefined /* BOOLEAN */,
                  workstation: undefined /* STRING */
                  useProxy: undefined /* BOOLEAN */,
                  withCookies: undefined /* BOOLEAN */,
                  proxyHost: undefined /* STRING */,
                  url: url /* STRING */,
                  content: content /* JSON */,
                  timeout: undefined /* NUMBER */,
                  proxyPort: undefined /* INTEGER */,
                  password: undefined /* STRING */,
                  domain: undefined /* STRING */,
                  username: undefined /* STRING */
};
// result: JSON
var result = Resources["ContentLoaderFunctions"].PostJSON(params);

 

A Note About Security

Salesforce has a few ways to authenticate your session.  The method described in this blog is the least secure way because ThingWorx has visibility to the username and password of the Salesforce account.  There are two other ways to authenticate and both use callback URLs.  Basically, a user sends a call to the login endpoint and enters user and password information directly into the Salesforce environment.  Salesforce then redirects to a callback URL that is appended with an authorization token.  If you’d like to implement one of the more secure methods, I would suggest using a REST endpoint to a ThingWorx service as your callback URL. More specifically, create a service that has a string input called “code.” Now, change your callback URL in your Salesforce connected app to something like https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=&redirect_uri=>.  Now, when you navigate to the login link, it will send your authorization code to your ThingWorx service (this is because it appends “&code=” to the URL).  You’ll need to then send that code via the Content Loader Functions to receive your authorization token.  One thing to note is that the ThingWorx instance must be on HTTPS.  Salesforce does not allow HTTP callback URLs.  More information about Authentication can be found at https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_authentication.htm

If you have any questions about this blog or ThingWorx in general, don’t hesitate to leave a comment or contact EAC Product Development Solutions.

Creating Ideal Translation Workflows for Optimum Results 

In Part Two of this post on coupling products for translation, we’ll discuss the specific steps that are required to implement complete translation projects – from managing technical content objects to managing costs and file collaboration. Refer to Part One for the overall solution design which shows the strengths of PTC’s Translation Manager, Windchill ProjectLink, workflow, reporting, and multi-lingual publishing and how they can be leveraged for translation.

The Process 

There are six process components to the overall translation solution. The process starts and ends with PTC’s Translation Manager. Windchill ProjectLink is nested in the middle of the process to facilitate the business project, cost collaboration, and file transfers with Translation Service Providers.

Step 1. Designate Objects for Translation 

The first step of the process begins with source content that is ready for translation to the target language(s). The content is stored in Product or Library folders in Windchill/Arbortext Content Manager. Here the project owner identifies complete document structures or document objects to be translated. A translation work package is created for the objects. The Translation Service Provider and target language(s) are designated with the creation of the translation package. Languages and Translation Service Providers are configurable.

At the completion of this step, the content is prepared for translation. It results with a collection of XML objects to be translated in a zip file. The source objects are set to the In Translation lifecycle state and the source content continues to be managed in relation to other content and states.

Step 2. Create Translation Project 

In the second step, ProjectLink is used to create a translation project that contains any business-related activity required for traceability. This activity includes deadlines and due dates, assign internal resources to the project, and expose the project to Translation Service Provider(s) or other external users outside your firewall. Any cost information, such as Requests for Quote and quotations received can also be stored under the project.

To start, the translation zip package is posted to the project. From here, the package is available for workflow and lifecycle activities as well as for collaboration with Translation Service Providers. If a process for approving translation costs is required, the cost approval workflow would be executed on the translation package stored in the project. Providers will be able to see the source content in order to estimate the level of effort and designated project participants can see cost approved or not approved activity.

Step 3. Route Objects for Translation 

This step in the workflow is for actual translation activities. Here Translation Service Providers can:

  1. Checkout and Download the package when it is ready to translate and
  2. Checkin and Upload the package when the work is complete.

This activity makes use of the translation package on ProjectLink so that collaboration with users outside your firewall can work on the project. The user interface is self-serving and provides traceability out-of-the-box. The zipped file is automatically iterated and historical versions are maintained on checkin so that everyone on the project is aware of the project status. Users can schedule alerts to immediately know when a critical threshold is reached. Therefore having the lifecycle states in ProjectLink enables real-time reporting on activities to show key performance indicators. Is the project on time? On budget?

Step 4. Route Translated Collateral for Approval 

The approval workflow activity in step four supports reviewing translated content delivered by the Translation Service Provider. Reviews may be performed by local native language review teams or it may include users that have other roles on the project. This activity uses the translation package on ProjectLink so that collaboration for users inside or outside of your firewall can continue to work on the translation. As a result of this workflow, updates can be made either by the Translation Service Provider or by home team members.

Once the translation is approved, the translation project can be concluded and all ProjectLink activities closed. Even so, an organization may still elect to store invoices and final cost information in the project for matrix reporting and future planning purposes.

Step 5. Store Objects in Translation Library 

After objects are translated, the final translation zip package is returned to the Translation Library where XML objects and images are stored. Here the translated target objects are bound to specific revisions and iterations of source objects for each language. For clarity on object status, objects are marked “Translated” or “Translated, Ready for Publish”.

When the objects are returned to Windchill/Arbortext Content Manager they can be published, updated, and iterated just like any other object. This is important since changes may be necessary to:

  1. validate the markup;
  2. facilitate aesthetics for publishing;
  3. change product names, service marks or other marketing decisions;
  4. change dates or other metadata.

Step 6. Route Assembled PDF Document for Approval 

In an environment with shared document components, status checks are necessary to verify that all objects included in the document are ready for publishing. This is a key element of the process since some objects may be In Translation, others may be at earlier iterations with no recent updates, or they could be universal images that require no translation. When all objects in the translated document are Ready for Publish, the published document is created, and routed for review and approval. This may be the first time that a translated document is being reviewed as a whole, thus it may be the first time that all content is reviewed relative to the content around it. At this point, it is expected that any changes made during this stage would be made by the home team for content stored securely behind the firewall.

The document review and approval process should be the same as your usual published document review process with different resources for languages. Documents can contain a single language or there may be multiple languages per document depending on the style guidelines for your organization.

Summary

For anyone that has been involved in the translation process, you can likely sympathize on how complex and challenging the tasks can be. By putting ProjectLink to work in your translation process, it does not have to be the case. With PTC’s Translation Manager and Windchill ProjectLink, workflow activities can be more transparent, helping to streamline the translation process across all documents and languages that need to be managed. If you have questions about how ProjectLink, Translation Manager, or multi-lingual publishing solutions can be integrated into your organization, connect with our technical publications team today.

Learn More

Be sure to read Part One of this post to learn more about the solutions being deployed in the workflow being described.

Why Translation Workflows Matter

For companies who require product documentation to be localized for regional use, the sheer number of translated objects makes translation management very important to the business and organization as a whole. Suppose, for the purpose of simple math, that you are translating to 9 languages. One source language plus 9 target languages is 10 languages total. That means up to 90% of the content you are managing is translated. 10% of those objects could be global images that do not require translation, which would drop managed translated content to 80%. In global companies, it is fair to say that a large majority of the content you are responsible for is translated.

One might think that the translation process would simply involve handing off copies of documents to translation teams and then waiting a few days/weeks for the local language versions to arrive, but in reality this process is much more complex. Even when the material is developed in a sophisticated technical documentation tool like PTC Arbortext, it remains necessary to closely administer this activity to avoid risks associated with mandates that vary in different geographies, inefficient file tracking, incomplete reviews, and delays throughout the translation lifecycle.

This is the first of a two part series that discusses how to optimize translation processes by coupling two complementary tools, PTC Translation Manager and PTC ProjectLink. By combining these tools, organizations can overcome several obstacles that either slow workflow processes or increase costs during the translation of technical documentation. Part one outlines these tools and the processes they are designed to address. Part two details how more efficient translation workflows can be arranged in order to expand past administering translated XML objects, to include management of peripheral translation activities such as cost quotations, file sharing, collaboration with translation service providers, and quality assurance processes.

PTC’s Translation Manager

Translation Manager is a component of the PTC Windchill Service Information Manager. The Translation Manager prepares content for translation by identifying document components to be translated, creating work packages for translation or translation service providers, and setting the InTranslation lifecycle state. Key features include:

  • Automate the creation of translation packages using workflows
  • Restrict creation of translation packages to authorized translation users
  • Generate a translation package from a Publication Structure or an Information Structure or
  • include select document objects by assigning the proper translation attribute and life cycle state
  • Automatically associate translated dynamic documents with their source objects
  • Identify whether a translation exists for a source document or not
  • Bind specific revisions and iterations of source objects to translated target objects
  • Publish translated dynamic document structures.

Post-translation, the Translation Manager stores content by linking translated objects to source document objects in the translation library and sets the Translated lifecycle state.

Windchill ProjectLink

ProjectLink enables defining and executing project plans as well as associating project tasks with product deliverables. Through a self-administered virtual workspace, ProjectLink provides project management capabilities and access to accurate product information for resources inside or outside of your firewall.

In this solution, Windchill ProjectLink is featured to facilitate translation tasks outside your organization.

Windchill Workflow and Reporting Features

Workflow and Reporting are core features of the PTC product suite and are available in all Windchill-based products including Arbortext Content Manager, Service Information Manager,  and ProjectLink.

Workflow

Windchill Review and Approval Processes are used to automatically set the state of objects to the target lifecycle state and invite a list of Reviewers to provide comments.

Reporting

Windchill offers multiple tools to help decision-makers easily visualize trends, patterns and relationships using graphical and drill-down reports of key performance indicators. Simple and easy-to-use reporting and charting tools enable users to configure and save reports.

Publishing

PTC Arbortext Publishing Engine is a server-based system that assembles XML content and automatically publishes the content in both print and electronic forms, all with high-quality layout and formatting.

Stylesheets

Predefined stylesheets are used for layout and page composition. There can be different formatting options based on the language attribute assigned in the XML file.

XLIFF for Generated Text

Text that is generated by the stylesheet is translated once and stored for future use in an independent file. For example, text like the word “Table” is not translated with content. This is supported using XLIFF technologies. XLIFF is the XML Localization Interchange File Format which is used to store extracted text and carry the data from one step to another in the localization process.

Summary

As you can see, there are some pretty sophisticated tools available to support the translation process. The challenge is knowing how to leverage these tools to create a process that maximizes efficiency. Stay tuned, because we will be discussing just that in part two.

EAC Product Development Solutions (EAC), a leading provider of product development technology and services, is pleased to announce the acquisition of the Arbortext Business Unit of TerraXML. This acquisition makes EAC unique in providing a complete end-to-end systematized solution set for managing product information, executing processes within that system, and publishing relevant information both inside and outside the enterprise.

March 19, 2014 — EAC Product Development Solutions (EAC) expands capabilities and services through the acquisition of TerraXML’s Arbortext Business Unit. This acquisition aligns EAC with industry trends toward Service Information Management (SIM), Service Lifecycle Management (SLM), and automated publishing of technical information. The Arbortext Business Unit will operate as the EAC Product Development Information Services group or PDIS, and provide implementation, customization, development, and support for the Arbortext product line.

Thane Hathaway, President and CEO of EAC said: “Small and medium businesses (SMB’s) need to manage and publish accurate product information in real time, across multiple platforms just like the Fortune 500’s, but they’ve never had a world class and affordable solution. With this acquisition, we’ve gained the unique ability to implement and support an end-to-end PLM and publishing system specifically tailored for SMB. We look forward to satisfying this market need while continuing to grow and develop these tools.”

Cory Huey, Vice President of Services at EAC said: “This acquisition opens the doors to many new possibilities. In the future, we will develop integrated dynamic publishing products that small companies can more easily afford and deploy. I’m excited to see where the market takes us from here.”

Acquiring the Arbortext Business Unit of TerraXML enables EAC to enter new markets and provide end-to-end solutions to the product development and manufacturing industries. Arbortext allows product companies to easily create products and technical publications and make that information available to customers, dealers, and service staff.

I’ve been a Mechanical Engineer for years. This means I’ve had many conversations with people regarding their opinions about the various CAD tools on the market. For the record, I’m a Creo and Pro/ENGINEER man. During these, sometimes heated, conversations I regularly hear people say that it takes too many mouse clicks to do something in Creo; whether that is creating a feature in sketcher mode or getting to the dialogue box to select a sketching plane for an extrude. Every time I hear this I have the same response. I tell them about a simple solution that’s built right into Creo. I use it every day. It’s the right mouse button.
The right mouse button (RMB) gives you several menu options depending on what mode you are in and what you are currently doing. For example if you are editing an extrude and you have the dashboard up and you hold down the right mouse button you will see options such as “Edit Internal Sketch, Clear, Surface, Thicken sketch, Flip Depth Direction, Add Taper, Show Section Dimensions.” I don’t know about you but I find that a lot faster and easier than digging through the dashboard.

This was just one quick example of using the right mouse button in Creo. Feel free to explore the right mouse button in other areas of Creo for different menu options. Let me know your favorite “short cuts” in the comments below.