4. Windchill API体系总览

Windchill 的二次开发本质上是在一套分层、分端的 Java API 体系上做扩展。理解这套体系,关键不是背类名,而是先建立三个判断维度:这段代码运行在哪个 JVM 里、它通过什么通道访问 Windchill 服务、它依赖的 API 在目标版本中是否稳定。这三个维度决定了包的选择、调用方式和兼容策略。

一、常用 API 包结构:按职责分层

Windchill 的 API 包名以 wt. 开头,按业务域划分。日常开发中高频出现的包大致可分为四层:

  • 基础服务层:wt.fc(持久化框架,Persistable、QueryResult、ReferenceFactory)、wt.session(SessionHelper、WTPrincipal)、wt.util(WTException、WTPropertyVetoException)。这一层是所有业务 API 的地基。
  • 业务对象层:wt.part(WTPart、WTPartMaster)、wt.doc(WTDocument)、wt.change2(变更对象)、wt.bom(BOM 结构)。这一层直接对应 PLM 数据模型。
  • 服务与流程层:wt.services(ServiceFactory、StandardService)、wt.workflow(工作流)、wt.lifecycle(生命周期状态)。
  • 扩展与集成层:com.ptc.*(PTC 扩展包,如 com.ptc.core.meta 元数据)、wt.method(远程方法调用基础)。

一个典型判断:如果你要查询某个零件的最新版本,用 wt.part.WTPart 配合 wt.fc.QueryResult;如果要触发一个审批流程,则要落到 wt.workflow 或 com.ptc.windchill.enterprise 相关服务。包的选择错误,往往在编译期不报错,运行期才抛 WTException。

二、服务端 API 与客户端 API 的边界

Windchill 是典型的 C/S 架构,但“客户端”并不等于浏览器。服务端 API 运行在 Method Server 的 JVM 中,可以直接访问数据库、缓存和事务上下文;客户端 API 运行在远程 JVM(如独立 Java 程序、批处理工具)或浏览器端(GWT/JavaScript),必须通过网络通道访问服务端。

服务端 API 的典型特征是:可以直接调用 PersistenceHelper.manager 做持久化操作,可以参与 wt.fc.Transaction 事务,可以访问 wt.session.SessionHelper 的当前上下文。客户端 API 则必须通过 wt.services.ServiceFactory 获取远程服务代理,所有调用都被序列化后发送到服务端。

常见误区:在客户端代码中直接 new WTPart() 并调用 persist(),这在服务端可行,在客户端会因缺少事务上下文而失败。客户端应通过服务接口操作,而不是直接操作持久化对象。

三、JCA 与 RMI:两种调用通道

Windchill 提供两种主要的远程调用方式,选择依据是部署形态和调用频率。

RMI(Remote Method Invocation)是传统方式,基于 Java 原生 RMI 协议,通过 wt.method.MethodServer 暴露远程对象。它的优点是配置简单、与 Java 对象模型贴合紧密;缺点是序列化开销大、跨防火墙能力弱、连接数受限于 RMI 线程池。适合内部工具、批处理、低频管理操作。

JCA(Java Connector Architecture)是更现代的集成方式,Windchill 通过 JCA 适配器将服务暴露为符合 J2EE 连接器规范的资源。它的优势在于连接池管理、事务传播、与外部应用服务器(如 Tomcat、WebLogic)的集成更规范。适合企业级集成、高并发场景、需要与外部系统共享事务边界的场景。

两者的调用代码结构差异明显。RMI 方式通常如下:

// RMI 方式:获取远程服务代理
RemoteMethodServer rms = RemoteMethodServer.getDefault();
rms.setUserName("wcadmin");
rms.setPassword("wcadmin");
Object result = rms.invoke("getLatestVersion", 
    "wt.part.WTPartHelper", null, new Class[]{String.class}, 
    new Object[]{"P-1001"});

JCA 方式则通过连接工厂获取连接,再获取服务:

// JCA 方式:通过连接工厂获取服务
InitialContext ctx = new InitialContext();
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:comp/env/eis/Windchill");
Connection conn = cf.getConnection("wcadmin", "wcadmin");
Interaction interaction = conn.createInteraction();
// 通过 interaction 执行服务调用

实际选型时,如果只是写一个定时同步脚本,RMI 足够;如果要和 SAP、MES 做事务级集成,JCA 更合适。

四、API 版本兼容策略

Windchill 版本升级(如 11.0 → 12.0 → 13.0)时,API 并非全部保持二进制兼容。PTC 的兼容策略大致分三档:

  • 稳定 API:wt.fc、wt.part 等核心包中的公开方法,跨大版本基本保持签名不变,但可能新增重载方法。
  • 受控变更 API:com.ptc.* 下的扩展类,方法可能被标记 @Deprecated,并在下一个大版本移除。升级前必须检查编译警告。
  • 内部 API:以 *.impl、*.internal 结尾的包,不保证兼容,禁止在正式扩展中直接依赖。

工程上的兼容策略可以归纳为三条:第一,编译期用目标版本 SDK 重新编译,不要直接搬运旧 jar;第二,运行期做版本探测,通过 wt.util.WTProperties 读取 wt.version,对差异分支做适配;第三,封装适配层,把易变 API 收敛到自己的 XxxAdapter 类中,升级时只改适配层。

一个可复用的版本探测片段:String ver = WTProperties.getLocalProperties().getProperty("wt.version");,返回如 12.0.0,据此决定走哪条分支。

五、整体调用关系图

下图把上述四个维度整合为一张调用关系图:左侧是客户端侧,右侧是服务端侧,中间是 JCA/RMI 两条通道,底部标注版本兼容的收敛点。

客户端 JVM 独立 Java / 批处理 / 外部系统 客户端 API ServiceFactory 代理 JCA 连接工厂 ConnectionFactory RMI 客户端 RemoteMethodServer 版本适配层 XxxAdapter wt.version 探测 调用通道 JCA 连接池 / 事务传播 / 企业集成 RMI 序列化 / 内部工具 / 低频调用 网络边界 / 序列化边界 事务上下文不跨通道自动传播 服务端 JVM Method Server 服务端 API wt.fc / wt.part / wt.change2 持久化框架 PersistenceHelper / 事务 业务服务 wt.workflow / wt.lifecycle 数据库 / 缓存 Oracle / SQL Server Windchill 缓存层 版本兼容收敛点 稳定 API 直用 · 受控 API 适配 · 内部 API 禁用 客户端与服务端之间必须经过 JCA 或 RMI 通道,事务与 Session 上下文不自动跨通道传播

把这张图记在脑子里,实际开发时的判断顺序就清晰了:先确认代码跑在哪一侧,再决定用服务端 API 还是客户端代理,然后选 JCA 或 RMI 通道,最后把易变 API 收进适配层。这样即使 Windchill 从 12.0 升到 13.0,改动量也能控制在适配层内部,而不是散落到整个工程。