Windchill Stickiness in 10.x

In my recent post Windchill Stickiness I wrote about the Windchill Stickiness and how to clear in Windchill 9.1. Here we will discuss how to clear Windchill Stickiness in Windchill 10.x

How to reset Windchill Stickiness in 10.x?
  1. Navigate to http:////app/netmarkets/jsp/user/utilitiesList.jsp
  1. Click “Reset Server Stickiness”. It will ask the confirmation

  1. Click OK to clear server stickiness
  2. To remove all client stickiness, delete all your temporary internet files (usually in the Tools menu), close all browser windows, and restart the browser.

Soft Type – How to get type definition reference id

When we want to find the list of soft type objects and with the help of QuerySpec in Windchill, we need to use soft type’s type definition reference id in the QuerySpec condition.
Below code snippet will be useful in writing this QuerySpec

TypeDefinitionReference typeDefRef = TypedUtility.getTypeDefinitionReference("com.maheshmhetre.epmdoc.TestEPMDocument");
if (typeDefRef != null) {
qs.appendWhere(new SearchCondition(EPMDocument.class,
"typeDefinitionReference.key.id",
SearchCondition.EQUAL,
                           typeDefRef.getKey().getId()));
}


Here ‘com.maheshmhetre.epmdoc.TestEPMDocument’ is the Internal Name of the soft type. This value can be retrieved from soft type details from Type and Attribute Manager.

Windchill Part Usage Link


This is an IteratedUsageLink where a specific WTPart uses a WTPartMaster (actually it will use one of the WTParts associated with the WTPartMaster based on a config spec) and the part uses a specific Quantity (with unit of measure) of the part master as a component of its structure. WTParts can use other parts to build assemblies using the WTPartUsageLink. The WTPartUsageLink’s aggregated Quantity can be used to indicate the amount of the component that is being consumed.
Note that since the link is between a WTPart and a WTPartMaster it will be necessary to use a config spec (usually WTPartConfigSpec) to select the correct version of the WTPartMaster, which is a WTPart.
For example:
To build a car there are 4 tires for each car built. For a hammock there might be 2 end ropes that are three feet long.

Part_1 A.1 is dependent on Part_2 master object.

Even after new revision/iteration Part_1 B.1 is link to the Part_2 irrespective of Part_2 iteration number i.e. the parent object’s (Part_1) all iterations are always linked to the child’s (Part_2) latest iteration.

Model Diagram:

JavaDoc:
wt.part

Class WTPartUsageLink
java.lang.Object
 wt.fc.WTObject
  wt.fc.ObjectToObjectLink
      wt.vc.struct.IteratedUsageLink
          wt.part.WTPartUsageLink
public class WTPartUsageLink
extends IteratedUsageLink
implements Externalizable
UI Navigations:
To see the part usage, navigate to parent part details page -> third level navigations -> Structure -> Product Structure table
API Navigations:
To get the usage parts, we need to navigate through this link table. The service APIs are available in WTPartService class.
The relevant methods are (Please refer JavaDoc for more details)
QueryResult
getUsedByWTParts(WTPartMaster partMaster)
         Navigates the WTPartUsageLink along the usedBy role, returning a QueryResult of WTParts.
QueryResult
getUsesWTPartMasters(WTPart part)
         Navigates the WTPartUsageLink along the uses role, returning a QueryResult of WTPartUsageLinks.
Persistable[][][]
getUsesWTParts(WTList parts, ConfigSpec configSpec)
         Navigates from many used-by parts to their uses part masters and applies a ConfigSpec to select the iterations of the uses parts.

Windchill Document Dependency Link


This is a version-specific relationship between two documents i.e. WTDocument to WTDocument link.  A reference between two documents can be created to show a dependency on another document. A document may reference some information in another document, so during a create or update, a reference to that document is added. The references relationship has a comment attribute that can be used to explain why the reference exists or what the dependency is.
For example:
A document is depends on another document.

Doc1 A.1 is dependent on Doc2 A.1

After new revision/iteration Doc1 B.1 is dependent on Doc2 B.1

Doc1 A.1 is dependent on Doc2 A.1. This is a version dependency. If the Doc1 get revised/iterated, the dependent document’s will also get updated.
Model Diagram:

JavaDoc:

wt.doc
Class WTDocumentDependencyLink
java.lang.Object
 wt.fc.WTObject
  wt.fc.ObjectToObjectLink
      wt.vc.struct.IteratedUsageLink
          wt.doc.WTDocumentDependencyLink
public class WTDocumentDependencyLink
extends IteratedUsageLink
implements Externalizable

UI Navigations:
To see the dependent documents, navigate to main document’s details page third level navigations -> Related Objects -> Documents
To add the dependent documents, from ‘References Documents’ use ‘Add’ or ‘Associate New’ table level action on main document. You can add dependency comment from the row level actions.
MainDoc depends on doc01. MainDoc details page
If you see the doc01 document, related document you can see MainDoc is dependent on doc01
API Navigations:
To get the depedent documents, we need to navigate through this link table. The service APIs are available in WTDocumentService class.
The relevant methods are (Please refer JavaDoc for more details)
QueryResult
getDependsOnWTDocuments(WTDocument document)
         Return a QueryResult of WTDocuments that the given WTDocument is dependent on.
QueryResult
getDependsOnWTDocuments(WTDocument document, boolean onlyOtherSides)
         Return a QueryResult of WTDocuments that the given WTDocument is dependent on.

Windchill Document Usage Link


The WTDocumentUsageLink is an IteratedUsageLink between WTDocuments and WTDocumentMasters and used to create uses relationships between documents or document structure.
For example:
Several documents can contain the same glossary or one document can be made up of several sub-documents.
Documents should use this if a document is made up of subdocuments and the sub-documents can be reused by other documents, or need to be controlled separately.


The main document is linked to the other document’s master objects. Here main document is linked to the WTDocumentMaster objects of document_1, document_2 and document_3.
This means main document is always pointing to the latest copy of all linked document even they get new version or iteration.
Model Diagram:


JavaDoc:

wt.doc Class WTDocumentUsageLink
java.lang.Object
 wt.fc.WTObject
  wt.fc.ObjectToObjectLink
      wt.vc.struct.IteratedUsageLink
          wt.doc.WTDocumentUsageLink
public class WTDocumentUsageLink
extends IteratedUsageLink
implements Externalizable
UI Navigations:
To see the usage documents, navigate to main document’s details page -> Structure -> Document Structure table
To add the child documents, use ‘Add Documents’ row level action on parent document.
API Navigations:
To get the usage documents, we need to navigate through this link table. The service APIs are available in WTDocumentService class.
The relevant methods are (Please refer JavaDoc for more details)
Enumeration
getOrderedUsesWTDocumentMasters(WTDocument document)
         Navigates the WTDocumentUsageLink along the uses role, returning a Enumeration of WTDocumentMaster.
Enumeration
getOrderedUsesWTDocuments(WTDocument document, ConfigSpec configSpec)
         Applies the configSpec to the result of navigating the WTDocumentUsageLink along the uses role; returns a Enumeration of Persistable[], in which the WTDocumentUsageLinks are at the 0th position and the corresponding iterations (or master if there is no corresponding iteration) in the 1th position.
QueryResult
getUsedByWTDocuments(WTDocumentMaster documentMaster)
         Navigates the WTDocumentUsageLink along the usedBy role, returning a QueryResult of WTDocuments.
QueryResult
getUsesWTDocumentMasters(WTDocument document)
         Navigates the WTDocumentUsageLink along the uses role, returning a QueryResult of WTDocumentMaster.
QueryResult
getUsesWTDocuments(WTDocument document, WTDocumentConfigSpec configSpec)
         Applies the configSpec to the result of navigating the WTDocumentUsageLink along the uses role; returns a QueryResult of Persistable[], in which the WTDocumentUsageLinks are at the 0th position and the corresponding iterations (or master if there is no corresponding iteration) in the 1th position.
QueryResult
getUsesWTDocumentUsageLinks(WTDocument document)
         Returns the WTDocumentUsageLinks resulting from navigating the WTDocumentUsageLink along the uses role.

Windchill Rose Web Publisher


While working on Windchill customization, sometimes we need to look into the object models. In Windchill 9.1 we can use the Rational Rose tool for the same but most of the times the tool is not available to all the developers. In this scenario, we can use the Windchill Rose Web Publisher tool to view the object model.

Access Windchill Rose Web Publisher using URL:


















Navigate to Logical View -> Assembly -> Module -> appropriate package and double click on item. Please find below screenshot for wt.doc package object model

Note: There may be issue in panel scrolling. Try different browsers. Mostly works with IE.

Custom Util: CSV File Writer

In many utilities or operations we want output to be in CSV file format. This is frequently used operation so it is always better to have util class which can handle all this CSV file writing.
Posting CSV file writer util class along with a test class. Please share your thoughts to optimize this code.

CSV File Writer:
package com.blogspot.maheshmhetre.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Util class used for CSV file writing.
 * @author mmhetre
 *
 */
public class CSVFileWriter {

 public static final String FILE_SEPARATOR = System.getProperty("file.separator");

 private StringBuilder outputStr = null;
 private FileWriter fw = null;
 
 private String csvFilePath = ""; 

 /**
  * Constructor.
  * @param filePathWithoutFileName CSV file path without file name
  * @param fileName File Name without file extension/type
  * @param shouldAppendDateAndTime Should append timestamp to the file name? If true, the final file name 
  *          will be fileName_timestamp.csv else fileName.csv 
  * @throws IOException
  */
 public CSVFileWriter(String filePathWithoutFileName, String fileName, boolean shouldAppendDateAndTime) 
  throws IOException{
  
  if(shouldAppendDateAndTime){
   DateFormat dateFormate = new SimpleDateFormat("yyyy-MM-dd");
   String date = dateFormate.format(new Date());
   
   DateFormat timeFormat = new SimpleDateFormat("hh-mm-ss");
   String time = timeFormat.format(new Date());
   
   csvFilePath = filePathWithoutFileName + FILE_SEPARATOR + fileName + "_" + date + "-" + time + ".csv";
  } else {
   csvFilePath = filePathWithoutFileName + FILE_SEPARATOR + fileName + ".csv";
  }
  
  fw = createFileWriter(csvFilePath);
  outputStr = new StringBuilder();
 }
 
 /**
  * Add row in the CSV file.
  * @param commaSeperatedStr Row data. The comma separated string.
  */
 public void addRow(String commaSeperatedStr){
  if (outputStr == null)
   outputStr = new StringBuilder();
  
  if (csvFilePath == null)
   return;
  
  outputStr.append(commaSeperatedStr);
  outputStr.append("\n");
  
  if (outputStr.length() < 5000) 
   return;  

  //if output string size more than 5000 flush to the file
  try {   
   fw.write(outputStr.toString().toCharArray());
   fw.flush();
   outputStr = new StringBuilder();
  }catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 /**
  * Stop file writing
  */
 public void stopFileWriting(){  
  try {
   if (outputStr != null) {
     if(outputStr.toString().trim().length() != 0) {
      fw.write(outputStr.toString().toCharArray());
     }
     
     fw.close();
     fw = null;
     csvFilePath = null;
     outputStr = null;
   } 
  }catch (Exception e) {
   e.printStackTrace();
  }
 }

 /**
  * Get CVS file path
  * @return
  */
 public String getCSVFilePath(){
  return csvFilePath;
 }

 private FileWriter createFileWriter(String fileName) throws IOException{
  File aFile = new File(fileName);  
  FileWriter fw = new FileWriter(aFile, true);
  return fw;
 }
}
CSV File Writing Test Class:
package com.blogspot.maheshmhetre.util;
import java.io.IOException;

import wt.util.WTException;

public class TestCSVFileWriter {

 private static final char COMMA_SEPERATOR = ',';
 private static String CSV_FILE_DIR = System.getProperty("user.dir");
 
 private CSVFileWriter csvFileWriter = null;
 
 public static void main(String[] args) {

  TestCSVFileWriter fileWritingTest = new TestCSVFileWriter();
  try {
   for (int i = 0; i < 10; i++) {
    //adding random cell data. Add actual data here
    fileWritingTest.addRowToOutputCSVFile(i + "qq", i + 2 + "tt", i + 5 + "zz");
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (fileWritingTest.csvFileWriter != null) {
    fileWritingTest.csvFileWriter.stopFileWriting();
   }
  }
 }
//Change method signature according to your output CSV file format
private void addRowToOutputCSVFile(String cellOne, String cellTwo, String cellThree) throws WTException{
//Create output CSV file if not available
try { if(csvFileWriter == null){ //pass your desired file dir csvFileWriter = new CSVFileWriter(CSV_FILE_DIR, "MyCSVFile", true); } } catch (IOException e) { throw new WTException("Error while creating CSV File. " + e); } try { csvFileWriter.addRow(cellOne + COMMA_SEPERATOR + cellTwo + COMMA_SEPERATOR + cellThree); } catch (Exception e) { throw new WTException(e); } } }
You can download code here: CSVFileWriter TestCSVFileWriter