Community Tip - You can change your system assigned username to something more personal in your community settings. X
According to some of the research I have read that Info*Engine if the way to go to interact externally with Windchill. However, there seems to be some evidence to suggest that this is not the way to go moving forward as Info*Engine is/will be deprecated. Also, the REST API information seems to be somewhat incomplete.
- What is the preferred way to interact with Windchill and is there up-to-date documentation which illustrates how to access Windchill programmatically?
Solved! Go to Solution.
I've made some custom REST APIs on top of the existing swagger APIs @ <environment>/Windchill/netmarkets/jsp/restapi/index.html
I'm not sure if they are specific to FlexPLM or not, in which it might not work for what you're looking for.
I'll make a quick Hello World tutorial for you. I'm planning on making a little more in-depth tutorial later on my website but this should get you something to play around with.
We'll be modifying the rest.properties file @ WT_HOME/codebase/com/ptc/windchill/rest/rest.properties using this xconfmanager command from WT_HOME in a Windchill Shell:
xconfmanager --add type.rest.resources=com.custom.rest.HelloWorldService-t codebase/com/ptc/windchill/rest/rest.properties -p
or you can add it as a property in the $WT_HOME\codebase\com\lcs\xconfs\flexplm.rest.properties.xconf file.
As you probably guessed it you'll need to deploy your class file to the codebase/com/custom/rest/ directory after you finish compiling it.
HelloWorldService.java should look something like this:
package com.hmk.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Path("/custom") @Api(value="/HelloWorld") public class HelloWorldService{ @GET @Produces({MediaType.APPLICATION_JSON}) @Path("/example/{param}") @ApiOperation( value="Get a String of Hello World", notes="Returns Hello World and the parameter in the query parameter", response=String.class) public String helloWorld(@ApiParam(value = "a string parameter!") @PathParam("param") String param) throws Exception { String response = "Hello World" + param; ObjectMapper mapper = new ObjectMapper(); String output = mapper.writeValueAsString(response); //.withDefaultPrettyPrinter() return output; } }
That's just a simple GET operation, but we've been successful in PUT/POST operations as well. I'm currently working on a document/image page upload API at the moment.
I'm attaching a screenshot of the output of this demo.
Hope this helps and I didn't misunderstand your request.
You can try with Remote Method Invocation to connect to Windchill
Details in this link: https://www.ptc.com/en/support/article?n=CS254318
Thank you for your response.
According to the article, it still mentions that the preferred way to interact with Windchill is through SOAP and REST. From what I have seen, the REST API seems either incomplete or not mature. I will have to look at any references regarding SOAP.
Still do not understand why there is not a simple "Hello World" app or something for newbies to learn programmatic access to Windchill.
I've made some custom REST APIs on top of the existing swagger APIs @ <environment>/Windchill/netmarkets/jsp/restapi/index.html
I'm not sure if they are specific to FlexPLM or not, in which it might not work for what you're looking for.
I'll make a quick Hello World tutorial for you. I'm planning on making a little more in-depth tutorial later on my website but this should get you something to play around with.
We'll be modifying the rest.properties file @ WT_HOME/codebase/com/ptc/windchill/rest/rest.properties using this xconfmanager command from WT_HOME in a Windchill Shell:
xconfmanager --add type.rest.resources=com.custom.rest.HelloWorldService-t codebase/com/ptc/windchill/rest/rest.properties -p
or you can add it as a property in the $WT_HOME\codebase\com\lcs\xconfs\flexplm.rest.properties.xconf file.
As you probably guessed it you'll need to deploy your class file to the codebase/com/custom/rest/ directory after you finish compiling it.
HelloWorldService.java should look something like this:
package com.hmk.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Path("/custom") @Api(value="/HelloWorld") public class HelloWorldService{ @GET @Produces({MediaType.APPLICATION_JSON}) @Path("/example/{param}") @ApiOperation( value="Get a String of Hello World", notes="Returns Hello World and the parameter in the query parameter", response=String.class) public String helloWorld(@ApiParam(value = "a string parameter!") @PathParam("param") String param) throws Exception { String response = "Hello World" + param; ObjectMapper mapper = new ObjectMapper(); String output = mapper.writeValueAsString(response); //.withDefaultPrettyPrinter() return output; } }
That's just a simple GET operation, but we've been successful in PUT/POST operations as well. I'm currently working on a document/image page upload API at the moment.
I'm attaching a screenshot of the output of this demo.
Hope this helps and I didn't misunderstand your request.
Hi can u please upload your documentation for PUT/POST services for listing the rest api on top of the existing swagger APIs @ <environment>/Windchill/netmarkets/jsp/restapi/index.html.
I'm putting together some examples to present at the PTCUSER conference. I'll post a link to the necessary code-behind after that panel is completed.
private String adminGroup = LCSProperties.get("jsp.main.administratorsGroup", "Administrators");
Here's a simple example of a POST in FlexPLM that creates a new product given a node type. A CSRF_NONCE must be used for each POST/PUT/PATCH request to Windchill.
/** * @param nonce The required CSRF nonce for invoking a PUT/POST operation * @param nodeType The type of node the product is to be created under. Ex: "Product\\custom\\customBag" * */ @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) @Path("/products") @ApiOperation( value="Create a new product.", notes="Creates a new product and responds with its OID.", response=UpdateResponse.class) public Response createProduct(@NotNull @ApiParam(value = "The CSRF nonce as returned from the /security/csrf endpoint") @HeaderParam("CSRF_NONCE") String nonce, @ApiParam(value = "The type of node the product is to be created under. Ex: Product\\custom\\customBag") NodeType nodeType) throws Exception { try{ // 401 unauthorized if user is not an admin ClientContext lcsContext = ClientContext.getContext(); if(!lcsContext.inGroup(adminGroup.toUpperCase())){ UpdateResponse data = new UpdateResponse(null); data.setMessage("logged in user is not authorized to invoke this action."); return Response.status(401).entity(data).build(); } //201 Created new Product. LCSProductClientModel model = new LCSProductClientModel(); model.setFlexType(FlexTypeCache.getFlexTypeFromPath(nodeType.getNodeType())); model.save(); UpdateResponse data = new UpdateResponse(model.getBusinessObject().toString()); return Response.status(201).entity(data).build(); } catch(Exception e){ e.printStackTrace(); UpdateResponse data = new UpdateResponse(null); data.setMessage("something died, review error logs on server."); return Response.status(500).entity(data).build(); } }
package com.custom.rest; import com.fasterxml.jackson.annotation.JsonProperty; public class UpdateResponse { private String name; private String ID; private String message; public UpdateResponse(String id){ this.ID = id; } @JsonProperty("ID") public String getID() { return ID; } @JsonProperty("Name") public String getName() { return name; } @JsonProperty("Message") public String getMessage() { return message; } public void setMessage(String message){ this.message = message; } public void setName(String Name){ this.name = Name; } }
What is the POST URL that your program generates please?
The POST URL looks like this:
https://contoso.com:443/Windchill/servlet/rest/custom/products
In CURL with the POST body it looks like this:
curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" --header "CSRF_NONCE: 1NMY63TgFvhEOFsdfqBBrPyBbJsADBf5sOt1hs2rQakpUy3Vl4Ro09fRsdawGDmBvnKtSnqWHdcC+CW+v5eAt36HZL859CWDxnqUqp+KXe6p8XGzY5+F3n/2HebIjBWc=" -d "{
\"nodeType\": \"Product\\custom\\retail\"
}" "https://contoso.com:443/Windchill/servlet/rest/custom/products"
There are some provided Restful API.
What kind information customer need fetch from Windchill?
What's the version of Windchill?
Windchill PDMLink 11.0 M030-CSP06
What I am looking for is a simple, get started, "Hello World" application/code or documentation to be able to access Windchill programmatically without the use of Arbortext. I have downloaded the most recent JavaDoc but I have not seen anything to help a newbie with setting up their environment to talk to Windchill.
There are a number of things I am looking at with this endeavor. Maybe being able to check-out a document, edit the content and then check back in.
Thank you. Very Helpful!! to build the initial rest service in Windchill.
Pls add the steps to generate JSON output for other HTTP methods like POST, PUT etc.
Hi, did you complete this task?
I´m looking for a solution to do that.
We have a Java old solution to save data from a Part, that is triggered on Life Cycle, in a file (txt and xls). But, now we need to send by API to a outside ERP service (not on network any more). I wanna maintain this flow but not write a file, i need send by an API rest service.
Did you have a code you can share to give a idea for how to?
Thank you!