Windchill tips : building your project with Maven

| 10 minutes read

This article proposes to build a Windchill customization project using Maven.

Windchill is a software which often requires some tuning in order to meet the business requirements:

  • Objects business rules : initialization and constraints on PLM objects and properties
  • Custom actions : trigger actions and/or controls on some events (Create , Edit , Add link , etc.)
  • Changing the user interface : add complex GUI components, control component display and access rights
  • Third-party software integration

Some specific business rules can be implemented by “Out Of The Box” Windchill modules or by configuration. But when the time has come for advanced customization, it can be gainful to use a good software factory.

In this context, maven can help!

Usually, Windchill projects are built using Ant scripts, provided by PTC. These scripts allow you to perform standard build operations (clean, generate sources, compile, deploy).

As a complement to these standard build tools, Maven will support the following features:

  • Provide a uniform build system with common conventions
  • Manage dependencies with external libraries
  • Automate unit and integration testing
  • Provide guidelines for best practices development
  • Generate project documentation (maven site, test report, javadoc, etc.)

To illustrate the use of Maven in a Windchill project, let’s start with a simple example: implement and test a Windchill service that query parts (called PartQueryService).

Initialize the maven project

Prerequisites

The following software must be installed in order to run into the example:

  • Windchill and its components newly installed (understand without custom code already deployed in the codebase)
  • Latest stable version of Apache Maven
  • Your preferred IDE

Create a new maven project

To create a new maven project for Windchill, we will use a standard archetype available on the maven central repository

[jboulay@EKITO-DEV ~]$ mvn archetype:generate -DgroupId=fr.ekito.windchill -DartifactId=windchill-sample-rmi
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

This will create the following project layout (standard maven layout) that we will use to develop our sample project.

Sample project layout

Sample project layout

Windchill dependencies

As PTC doesn’t provide a public maven repository with the windchill jars (of course, it is a proprietary solution!), the next step will consist in populating your local maven repository with the jars used in the windchill classpath.

Let’s have a look on the windchill classpath

[jboulay@EKITO-DEV ~]$ echo $CLASSPATH
/opt/Windchill/codebase:/opt/Windchill/codebase/WEB-INF/lib/*:/opt/Windchill/lib/*:/opt/Java/lib/tools.jar:
/opt/Windchill/tomcat/bin/bootstrap.jar:/opt/Windchill/tomcat/bin/tomcat-juli.jar

With Windchill, most of the classes are directly available in the codebase directory, not in jars. And as Maven doesn’t authorize to add a directory in the dependencies, we will need to create a jar containing all java classes and all resources (*.ser files) of the codebase directory.

This can be done with the following ant script:

<target name="makeCodebaseJar" description="Create a jar of Windchill codebase to push in maven local repository">
    <jar destfile="${user.home}/tmp/codebase.jar"
        basedir="${wt.codebase}"
        includes="**/*.class,**/*.ser"
    />
</target>

When your jar is created correctly, you can proceed to its installation into your local maven repository with the following command :

[jboulay@EKITO-DEV ~]$ mvn install:install-file -Dfile=$HOME/tmp/codebase.jar -DgroupId=com.ptc
-DartifactId=codebase -Dversion=10.1.40.14 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true

The version parameter can be retrieved by executing the command

[jboulay@EKITO-DEV ~]$ windchill version

Timestamp: January 13, 2014 - 21:28:12 (GMT: Jan 13, 2014 8:28:12 PM)                                                                            

      Support   Support                                       Installer                                                    
      Datecode  Release Number  Release Id                    Sequence   Display Label
  --  --------  --------------  ---------------               ---------  ---------------------
      M040      10.1            pjl.10.1.40.14                02         Windchill ProjectLink 10.1
      M040      10.1            pdml.10.1.40.14               01         Windchill PDMLink 10.1
      M040      10.1            wsp.10.1.40.14                09         Windchill 10.1 Service Pack
      M040      10.1            whc.10.1.40.14                01         Windchill Help Center
      F000      10.1            infomodeler.10.1.00.38        01         Windchill 10.1 Information Modeler
      M040      10.1            ie.10.1.40.14                 01         Windchill 10.1 Info*Engine
      M040      10.1            wnc.10.1.40.14                07         Windchill 10.1 Services

  There are no patches installed.

To build this sample project correctly, you will also need to proceed with the installation of the following jars :

  • $WT_HOME/codebase/WEB-INF/lib/ie3rdpartylibs.jar
  • $WT_HOME/srclib/tool/Annotations

Note that when working with a development team, it would be more convenient deploying those jars in a shared maven repository like nexus or artifactory.

Project Object Model (pom.xml)

It’s now the time to write your pom.xml file. First, add the windchill dependencies with the scope “provided” (to avoid distributing the windchill jars in your target assemblies). You can also add junit that will be used during the maven integration-test lifecycle phase.

<dependencies>
	<!-- Windchill dependencies -->
	<dependency>
		<groupId>com.ptc</groupId>
		<artifactId>codebase</artifactId>
		<version>10.1.40.14</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>com.ptc</groupId>
		<artifactId>Annotations</artifactId>
		<version>10.1.40.14</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>com.ptc</groupId>
		<artifactId>ie3rdpartylibs</artifactId>
		<version>10.1.40.14</version>
		<scope>provided</scope>
	</dependency>

	<!-- Testing dependencies -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.11</version>
		<scope>test</scope>
	</dependency>

 

Then you need to configure the maven-compiler-plugin to use the right version of java

<plugin>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>2.3.2</version>
	<configuration>
		<target>1.6</target>
		<source>1.6</source>
		<executable>${java.home}/bin/javac</executable>
		<fork>fork</fork>
	</configuration>
</plugin>

where ${java.home} property point to the JDK delivered with Windchill.

Implement the Windchill Service

In this implementation, we will use the “Windchill Services” design pattern and the standard query API.

Create the following classes

  • PartQueryHelper
  • PartQueryService : interface of the service
  • StandardPartQueryService : default implementation of the service

Here is the code for the findByNumber method :

	@Override
	public QueryResult findByNumber(String partNumber) throws WTException {
		QueryResult qr = null;

		QuerySpec qs = new QuerySpec();

		qs.appendClassList(WTPart.class, true);

		qs.appendWhere(new SearchCondition(WTPart.class, WTPart.NUMBER,
				SearchCondition.LIKE, partNumber), new int[0]);
		qr = PersistenceHelper.manager.find((StatementSpec) qs);

		return qr;
	}

Don’t forget to add a factory for this service.

        public static StandardPartQueryService newStandardPartQueryService()
			throws WTException {
		StandardPartQueryService instance = new StandardPartQueryService();
		instance.initialize();
		return instance;
	}

When done, you can run maven “compile” goal:

[jboulay@EKITO-DEV windchill-sample-rmi]$ mvn compile                                                                              
Scanning for projects...                         

------------------------------------------------------------------------
Building windchill-sample-rmi 0.0.1-SNAPSHOT
------------------------------------------------------------------------

--- maven-resources-plugin:2.6:resources (default-resources) @ windchill-sample-rmi ---
Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
skip non existing resourceDirectory /workspace/windchill-github/windchill/windchill-sample/windchill-sample-rmi/src/main/resources

--- maven-compiler-plugin:2.3.2:compile (default-compile) @ windchill-sample-rmi ---
File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
Compiling 3 source files to /workspace/windchill-github/windchill/windchill-sample/windchill-sample-rmi/target/classes
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 4.530s
Finished at: Fri Jan 24 11:56:56 CET 2014
Final Memory: 18M/93M
------------------------------------------------------------------------

Deployment with ant

The maven-antrun-plugin can be used during pre-integration-test phase for deploying your service. The following tasks are required:

  • Stop the windchill servers
  • Deploy the service
  • Start the windchill servers

PTC provides standard ant target to stop and start the servers. AntContrib and Groovy are required to run these targets and must be declared in the plugin configuration :

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-antrun-plugin</artifactId>
	<version>1.7</version>
	<dependencies>
		<dependency>
			<groupId>ant-contrib</groupId>
			<artifactId>ant-contrib</artifactId>
			<version>1.0b3</version>
			<exclusions>
				<exclusion>
					<groupId>ant</groupId>
					<artifactId>ant</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.ant</groupId>
			<artifactId>ant-nodeps</artifactId>
			<version>1.8.1</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.groovy</groupId>
			<artifactId>groovy-all</artifactId>
			<version>1.7.4</version>
		</dependency>
	</dependencies>
	<executions>
		<execution>
			<phase>pre-integration-test</phase>
			<configuration>
				<target>
					<ant	antfile="${basedir}${file.separator}build.xml">
						<target name="pre-integration-test" />
					</ant>
				</target>
			</configuration>
			<goals>
				<goal>run</goal>
			</goals>
		</execution>
	</executions>
</plugin>

And your build.xml

<project name="windchill-sample-rmi" xmlns:antc="antlib:net.sf.antcontrib" basedir=".">

	<property environment="env" />
	<property name="wt.home" value="${env.WT_HOME}" />
	<property name="wt.bin" value="${wt.home}${file.separator}bin" />
	<property name="wt.codebase" value="${wt.home}${file.separator}codebase" />
	<property name="wt.codebase.webinf" value="${wt.codebase}${file.separator}WEB-INF" />
	<property name="wt.codebase.webinf.lib" value="${wt.codebase.webinf}${file.separator}lib" />

	<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" />

	<target name="windchill:stop" description="Stops windchill services">
		<ant antfile="${wt.bin}${file.separator}/windchill.xml" target="stop_windchill_services"/>
	</target>

	<target name="windchill:start" description="Starts windchill services">
		<ant antfile="${wt.bin}${file.separator}windchill.xml" target="start_windchill_services"/>
	</target>

	<target name="deploy">
		<copy todir="${wt.codebase.webinf.lib}">
			<fileset dir="${basedir}${file.separator}target${file.separator}">
				<include name="**/*.jar"/>
			</fileset>
		</copy>
	</target>

	<target name="pre-integration-test" depends="windchill:stop, deploy, windchill:start" />

</project>

Test with JUnit

You can then create a simple JUnit test. To be able to run this test, you will need to add the codebase directory in the classpath, otherwise the call to the windchill service will fail. This can be configured in the maven-failsafe-plugin (and in the JUnit run configuration if you use Eclipse)

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-failsafe-plugin</artifactId>
	<version>2.16</version>
	<configuration>
		<additionalClasspathElements>
			<additionalClasspathElement>${wt.home}/codebase</additionalClasspathElement>
		</additionalClasspathElements>
	</configuration>
	<executions>
		<execution>
			<goals>
				<goal>integration-test</goal>
				<goal>verify</goal>
			</goals>
		</execution>
	</executions>
</plugin>

Then in the JUnit test, you will have to initialize the connection to the Method Server before executing the test.

public class PartServiceIT {

	private static RemoteMethodServer remotemethodserver;

	@BeforeClass
	public static void init() {

		remotemethodserver = RemoteMethodServer.getDefault();
		remotemethodserver.setUserName("wcadmin");
		remotemethodserver.setPassword("wcadmin");
	}

	@Test
	public void testFindByNumber() {

		QueryResult result = null;
		try {
			System.out.println("testing PartQueryService.findByNumber()");
			result = PartQueryHelper.service.findByNumber("%");
			System.out.println("Result size : " + result.size());

		} catch (WTException e) {
			e.printStackTrace();
		}
		Assert.assertNotNull(result);
	}

}

You are now ready to run a full build of your project with mvn clean install command.

The whole example source code is available on github.

What I have learned about using maven on industrial projects

  • Maven is not made for installation : installing your customization will require Ant scripts as usual. These scripts can then be called in the maven-antrun-plugin to enable an integration testing of your applications.
  • Working with maven multi-module project can be tricky : packaging and deploying a windchill project requires to include all configuration files (xml, xconf, properties, etc.) and dividing such configuration in multiple modules can become a big bazaar. You have to consider creating a new module for technical components only. The main part of the Windchill customization should be kept in a single project.
  • Hard model generation : windchill hard modeling is usually managed with some annotations interpreted during compiling task. In a maven context, it requires some custom ant scripts to pull all the *.ser and registries deployed in the windchill codebase during annotation processing

Apart from this, maven has demonstrated its power to make continuous integration and project documentation easier.

You can now start to industrialize your windchill development projects!

Julien Boulay Author: Julien Boulay

Eclectic developer & architect
Activist for usability, performance and interoperability of systems.

My favorite quote : "The best feature is the one we don't need to develop !"

My hashtags : #windchill #java #talend #nodejs #angularjs #oss #docker

Like it?  Share  it!

Share Button