Showing posts with label Windchill Customization. Show all posts
Showing posts with label Windchill Customization. Show all posts

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 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

Windchill Stickiness


While working on Windchill 9.1, many times we come across situations where the first and second level navigation (tabs) are not appropriate and pointing to unexpected tab selections. Also some times on login by a user, the user is navigating to a URL all the times even you tried to change the URL like users are not able to access tabs because the stickiness context is wrong.
Examples: Clicking on Library tab leads to the Product tab.
This is because of stickiness in the Windchill. Such issues can be resolved by clearing the stickiness.
How to clear stickiness?
1.       Go to below UR
2.       The page will show you
a.    Clear sticky info for all tabs
b.   All first level navigation tab names with the link to clear respective stickiness
3.       Now you can clear all tabs stickiness or tab based by clicking on the relevant links
4.       To ensure that all client stickiness is removed, delete all your temporary internet files (usually in the Tools menu), close all browser windows, and restart the browser.

Windchill Command Line Utility Skeleton

In the last topic Windchill Remote Method Server Access API we saw how we can use RemoteMethodServer to invoke method server code remotely. Even though there are plenty of utilities available in Windchill OOTB, we came across various scenarios where we need to write our own custom utilities.
In this post I am trying to share the Windchill command line utility skeleton which uses RemoteMethodServer.
package com.blogspot.maheshmhetre.windchill.utilities;

import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;

import wt.method.RemoteAccess;
import wt.method.RemoteMethodServer;
import wt.session.SessionHelper;
import wt.util.WTException;

public class WindchillCustomUtilitySkeleton {

 //START of inner class - Server
 public static class Server implements RemoteAccess {
  
  public static void methodOne(String param1, String param2) {
   try {
    //Get login credentials
    SessionHelper.manager.getPrincipal();
    
    //Call core processing method
    WindchillCustomUtilitySkeleton utility = new WindchillCustomUtilitySkeleton(); 
    utility.doOperation(param1, param2);
    
   } catch (Exception e) {
    e.printStackTrace();
   }
   
   return;
  }
 } //END of inner class - Server

 private void doOperation(String param1, String param2) throws WTException{
  //TODO execute your utility logic
  System.out.println("This sysout will be available in method server log.");
 }
 
 public static void main(String[] args) {
  //TODO get utility input parameters
  //TODO basic validation

  System.out.println("This sysout will be available on console from where the utility is running.");
  //prepare input params
  //data types will depends on your method parameters and can be any valid object type
  Class argTypes[] = {String.class, String.class};//add all remote method parameter data types
  Object argValues[] = {"param_1_value", "param_2_value"};//respective data value
  
  //call remote method - pass inner class name, method name, arg types and arg values
  try {
   RemoteMethodServer.getDefault().invoke("methodOne", 
     "com.blogspot.maheshmhetre.windchill.utilities.WindchillCustomUtilitySkeleton$Server",
     null, argTypes, argValues);
  } catch (RemoteException e) {
   e.printStackTrace();
  } catch (InvocationTargetException e) {
   e.printStackTrace();
  }

  Runtime.getRuntime().exit(0);
 }
}

Please share your thoughts to improve this skeleton.