100% found this document useful (1 vote)
878 views35 pages

Day 2 Customization R1

This document provides an overview of request handling and MVC builders in Windchill customization. Request handling is now done using the Spring MVC framework, separating controllers from views. MVC builders are used to build component configuration and data, and can be registered through annotations or XML configuration. The document describes how to create an MVC component using JCA components for the UI design and returning data asynchronously using data sources.

Uploaded by

Vindya Prasad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
878 views35 pages

Day 2 Customization R1

This document provides an overview of request handling and MVC builders in Windchill customization. Request handling is now done using the Spring MVC framework, separating controllers from views. MVC builders are used to build component configuration and data, and can be registered through annotations or XML configuration. The document describes how to create an MVC component using JCA components for the UI design and returning data asynchronously using data sources.

Uploaded by

Vindya Prasad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

Windchill Customization

Day 02

1
Takeaway
At the end of this session you should be able to
Request Handling
MVC Builders
Table
Tree

22
Request Handling
Prior to the Windchill 10 release, JSP was serving as both the View and
Controller element when developing JCA clients. Moving forward, (from
Windchill 10.0 onwards), there is a clear separation between Controller
and View which is now implemented using the Spring MVC Framework
The primary motivations behind this move are:
enable components to be requested and rendered to any client technologies
to allow Windchill developers to use ‘standard’ 3rd party technologies and
training
improve the maintainability of the Windchill application moving forward
Instead of having multiple servlets as controllers, a main servlet is used
to make control more manageable. This is known as the ‘Front
Controller Pattern’ where a main DispatcherServlet acts as the Front
Controller

33
Request Handling
The servlet and servlet mapping for the Web container is defined in <Windchill>\codebase\WEB-INF\web.xml. The
below mentioned url patterns are mapped to Spring DispatcherServlet and hence will be termed as MVC requests.
<servlet-mapping>
<servlet-name>MVCDispatcher</servlet-name>
<url-pattern>/servlet/WizardServlet/*</url-pattern>
<url-pattern>/servlet/ActionsMenu/*</url-pattern>
<url-pattern>/servlet/RecentList/*</url-pattern>
<url-pattern>/servlet/Navigation/*</url-pattern>
<url-pattern>/ptc1/*</url-pattern>
<url-pattern>/app/*</url-pattern>
<url-pattern>/gwt/*</url-pattern>
</servlet-mapping>
<servlet>
<description>MVC Dispatcher Servlet</description>
<servlet-name>MVCDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

44
Request Handling
Application Context
An application context represents the set of configuration files that are used to
provide configuration information to the application and is defined in
$WT_HOME/codebase/WEB-INF/MVCDispatcherservlet.xml. This configuration file
is used to :
Import all the Spring configuration files that reside in the WT_HOME/codebase/config/mvc
folder. Any custom configurations should be defined in
$WT_HOME/codebase/config/mvc/custom.xml
Define the handler mappings by loading the mappings specified in the properties files in
$WT_HOME/codebase/config/mvc. Any custom handler mappings should be defined in
$WT_HOME/codebase/config/mvc/custom.properties

55
Request Handling
Request Handling by Spring
Requests are handling in the following
manner
The Client requests for a Resource in the
Web Application
The Spring Front Controller, will intercept the
Request and then will find the appropriate
handler based on the handler mapping
(configured in Spring configuration files).
The Handler Mapping is used to map a
request from the Client to Handler.
With the help of Handler Adapters, the Spring
Front Controller will dispatch the Request to
the Handler.

66
Request Handling
Handlers
An OOTB handler has been provided to handle
requests to build components -
com.ptc.mvc.components.ComponentController. It
prepares a ModelAndView,
(org.springframework.web.servlet.ModelAndView),
which can be handled by the DispatcherServlet
When building a component, component data and
component description are required. Component
description will be represented via ComponentConfig
and a ComponentConfigBuilder provides them.
Component data will be represented via
ComponentData and a ComponentDataBuilder
provide them.ComponentConfig and ComponentData
together define the component information to be
shown in the UI and will be represented by
ComponentDefintion. It is the Model in MVC
paradigm, where as the ComponentController is the
Controller.

77
Request Handling
ComponentController Details
ComponentBuilderResolver finds the
ComponentConfigBuilder and
ComponentDataBuilder for the
componentId specified in the resource
defaultMappings defines the default
views for different ComponentConfig
ComponentParamsFactory create
ComponentParams from request and
response that will be made available in In the diagram above, the artifacts that are in green are
the builders Windchill Client Architecture specific ones,
the black ones are the ones provided by the component
owners.
88
MVC
Model View Controller : Model represents enterprise data and the business rules that govern
access to and updates of this data. View renders the model. Controller translates interactions with
the view into actions to be performed by the model
There are two types of Builders. The one that provides ComponentConfig are called
ComponentConfigBuilderand the one that provides the
ComponentData are called ComponentDataBuilder.
ComponentConfigBuilder :beans that implement com.ptc.mvc.components.ComponentConfigBuilder
ComponentDataBuilder :beans that implement any of the following interface
com.ptc.mvc.components.ComponentDataBuilder
com.ptc.mvc.components.ComponentDataBuilderAsync
com.ptc.mvc.components.TreeDataBuilderAsync

99
MVC Builder
Specifying the componentid
Typically the component ID that a builder maps to is declared using the @ComponentBuilder annotation in your
builder class declaration.
@ComponentBuilder(value = “{<componetId1>, <componetId2>}”)
public class MyBuilder extends … {}

If you wish to implement your config and data builders in separate classes, then you must supply an additional
ComponentBuilderTypeparameter to the @ComponentBuilder annotation.
For config builders, this looks like:
@ComponentBuilder(value=“<componetId>", type=ComponentBuilderType.CONFIG_ONLY)
public class MyConfigBuilder implements ComponentConfigBuilder …. {}

For data builders, this looks like:


@ComponentBuilder(value=“<componetId>", type=ComponentBuilderType.DATA_ONLY)
public class MyDataBuilder implements ComponentDataBuilder…

10
10
MVC Builder
TypeBased : To build certain components, you may need the Windchill Type of the context object playing
a role in finding the appropriate builder. For example you have an info page and you want to populate
the content based on the Windchill Type. For these scenarios, we have introduced an annotation
“TypeBased” that can be used in the builder, to attach the builder to a specific Windchill Type. This
works with ComponentBuilder.
@ComponentBuilder("compIdA")
@TypeBased(value="{WTPart, WTDocument}")
public class OOTBBuilder1 extends ……{
}

Registering Builders Once they have been created, builders must be registered with the Spring
framework. Builders can be registered either explicitly or via automated scanning process
1. Explicit Configuration
This is achieved by adding a bean declaration for the builder to $WT_HOME\codebase\
config\mvc\cstom.xml e.g. <bean class=”my.builder.class.name”/>
2. Automated Scanning
Add a base package declaration for the path to be searched in $WT_HOME\codebase\
config\mvc\cstom.xml e.g. <mvc:builder-scan base-package="com.ptc.windchill.enterprise.preference.mvc.builders"/>

11
11
MVC Builder

12
12
MVC Builder

13
13
MVC Builder
How to Create MVC component
In buildComponentConfig function, use JCA component for UI design.
JCA Components that implement ComponentConfig interface:
JcaTableConfig
JcaAttributesTableConfig
JcaTreeConfig
JcaAttributePanelConfig
JcaColumnConfig
JcaInfoConfig
JcaPropertyConfig
JcaPropertyPanelConfig

@ComponentBuilder("com.hkmc.cad.builder.packageHistoryTableBuilder")
public class PackageHistoryTableBuilder extends AbstractComponentBuilder {
@Override
public ComponentConfig buildComponentConfig(ComponentParams paramComponentParams) throws WTException {
ComponentConfigFactory localComponentConfigFactory = getComponentConfigFactory();
JcaTableConfig localJcaTableConfig = (JcaTableConfig) localComponentConfigFactory.newTableConfig();
return localJcaTableConfig;
}
}

14
14
Tools
Navigate Customization > Tools
MVC Builder Search: Find the Builder given a
componentId
<demo>
MVC Builder Scan Report: Find a report on
mvc-scan
<demo>
log4j.logger.com.ptc.mvc.scan=INFO should be
enabled
More Resources
JCA MVC
Javadoc

15
15
Data Source
Data Sources are an MVC infrastructure component for processing results and streaming them to the client
asynchronously. The basic strategy is to return large result sets to clients in chunks, along with an ID that can be used
to get more chunks.
The following modes are available when using Data Sources:
Synchronous
This is useful if you have all the data that need to be send to client with you already and want to put the data in DataSource so
that it can be send to the clients in chunks. The DataSource session takes in a list of objects that you want sent to the client and
returns you a DataChunk object, which contains the first chunk of data to be send to the client. If the List of data could fit in one
chunk, then the session doesn't even create a DataSource, it just returns you the chunk. Otherwise a DataSource is created with
the data, which can be polled later for additional chunks. The DataSource will be closed so that no more data can be added.
Asynchronous
In this case, you haven't got your data yet. You want to submit a task to get the data in a background thread and have the data
returned to the client later. We leverage the capabilities of Executor framework provided by Java.(for more details refer JavaDoc
of Executor) To create an asynchronous DataSource, the DataSource session takes a DataSourceTask which will be run by in a
background thread sometime in the future. It returns a DataSourceFuture object, so that you have a way to access the
DataSource information.

16
16
Data Source
Some of the benefits of using
DataSources are
Display data without overly
consuming client- and server-
side resources.
Allow users to interact with the
page while data is loading.
Improve perceived
performance.
Provide messaging and
feedback while data is loading.

17
17
MVC Abstract Builder

18
18
MVC Table Builder
A table builder class corresponds to a table configuration.
All the table-level as well as column-level properties should be configured in the builder class.
When creating a new builder class, you should typically extend one of the abstract base classes provided by the MVC
infrastructure:
AbstractConfigurableTableBuilder
Use this base class if you are implementating a tree or table that supports configurable table views. This base class is located
in the CoreHtmlComp module due to its dependency on the configurable table infrastructure.
AbstractComponentBuilder
Use this base class for tables and trees that do not support configurable tables
AbstractComponentConfigBuilder
Use this base class for info pages. You can also use this if you wish to separate your table or tree config builder from its data
builder (not a typical use case).
AbstractComponentDataBuilder
Use this base class for table and tree implementations where you have chosen to separate the config and data builder
implementations (not a typical use case).

19
19
MVC Table Builder
Implementing ComponentConfig When extending the abstract base builder classes it is not necessary to create
ComponentConfig directly, instead use the getComponentFactory() method.
TableConfig and ColumnConfig instance definitions are used to specify table and column level customizations as shown in the code snippet below:
//get the ComponentConfigFactory
ComponentConfigFactory factory = getComponentConfigFactory();
//get an instance of TableConfig
TableConfig table = factory.newTableConfig();
// General table properties
table.setId("com.ptc.training.mvc.simpleTable");
// add columns
ColumnConfig col1 = factory.newColumnConfig(ICON, true);
table.addComponent(col1);
Localizing component configurations
To localize values within your config builder, the Mvc infrastructure provides a new ClientMessageSource class. If you are
extending one of the abstract configuration base classes, then you can call getMessageSource(String) to create a message
source for a given resource bundle class name. ClientMessageSource works like WTMessage, but ensures that the locale
that you use is the client locale, rather than the locale that the server is running with.

20
20
MVC Table Builder
Implementing a ConfigurableTable
You may choose to implement your ConfigurableTable as a static inner class of your
builder, or to put it in a separate file. If you only intend to use it from within the builder
implementation, then PTC recommends defining it as a private static inner class, as
shown in the example below:
public class SimpleTable extends AbstractConfigurableTableBuilder {
@Override
public ConfigurableTable buildConfigurableTable(String arg0)
throws WTException {
return new MvcConfigurableTable();
}
private static class MvcConfigurableTable extends JCAConfigurableTable {
}.
}

21
21
MVC Table Builder
Common Table API Methods
There are a range of table, row and column settings that can be set during the table config implementation, below are
examples of the common ones available, (see JavaDoc for further details)
Sorting
ColumnConfig col = factory.newColumnConfig(“name”, true);
col.setDefaultSort(true);
col.setAscending(false);
Disabling ‘Search in List’
TableConfig tableconfig = factory.newTableConfig('myTable');
tableConfig.setFindInTableEnabled(false);
Adding a Toolbar
TableConfig table = factory.newTableConfig();
table.setActionModel("customToolbar");
Configuring Single Select Table
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
Table.setSingleSelect(true);

22
22
Exercise 1
Create a page with one MVC JCA Table which contains the list of parts

23
23
Exercise 1 : Builder
Configure an action that generate a MVC url, that builds a table with componentId “exercise1”
Define the new action in WT_HOME/codebase/config/actions/custom-actions.xml
Find the definition of “Customization” action model
Override it in WT_HOME/codebase/config/actions/custom-actionModels.xml
Load the updated action configurations.
Create a Table builder
Base package com.ptc.mvc.builders
Extend AbstractComponentBuilder
Annotate it with @ComponentBuilder
Provide the ComponentConfig
Provide the Data
Compile the class and restart the MethodServer

24
24
Exercise 1 : Code Snippets
private static final String RESOURCE = // add columns
"com.ptc.carambola.carambolaResource";
table.addComponent(factory.newColumnConfig(ICON, true));
@Override
table.addComponent(factory.newColumnConfig(NAME, true));
public ComponentConfig buildComponentConfig(ComponentParams
table.addComponent(factory.newColumnConfig(FORMAT_ICON,
params) throws WTException {
false));
ComponentConfigFactory factory = getComponentConfigFactory();
table.addComponent(factory.newColumnConfig(ORG_ID, false));
ClientMessageSource messageSource =
table.addComponent(factory.newColumnConfig(INFO_ACTION, false));
getMessageSource(RESOURCE);
ColumnConfig nmActionsCol =
TableConfig table = factory.newTableConfig();
factory.newColumnConfig(NM_ACTIONS, false);
table.setLabel(messageSource.getMessage("PART_TABLE_LABEL"));
// specify the actionModel for the action column
table.setSelectable(true);
((JcaColumnConfig) nmActionsCol)
// set the actionModel that comes in the TableToolBar .setActionModel("CustEx_table_row_actions");
table.setActionModel("mvc_tables_toolbar"); table.addComponent(nmActionsCol);
return table;
}

25
25
Exercise 1 : Code Snippets
@Override
public QueryResult buildComponentData(ComponentConfig config, ComponentParams params) throws WTException {
QuerySpec qs = new QuerySpec(WTPart.class);
qs.setQueryLimit(10000);
return PersistenceHelper.manager.find((StatementSpec) qs);
}

26
26
Exercise 2
Override the OOTB builder for Product List table to show its label as “My Products”
Find the builder for the current Product List Table
Override the OOTB Builder
Base package com.ptc.mvc.builders
Annotate it with @OverrideComponentBuilder
Compile the class and restart the MethodServer

27
27
Exercise 3
Create a page with multiple MVC JCA Components (Property Panel & Table) Configure an action that generate a MVC url, that builds a table
with componentId “exercise3”
Define the new action in WT_HOME/codebase/config/actions/custom-actions.xml
Find the definition of “Customization” action model
Override it in WT_HOME/codebase/config/actions/custom-actionModels.xml
Load the updated action configurations.

Create the builder


Base package com.ptc.mvc.builders
Extend AbstractComponentBuilder
Annotate it with @ComponentBuilder
Provide the MultiComponentConfig
Add Property Panel
Add the Table created in exercise1
Set the custom view (/custom/exercise3.jsp)

Provide the Data for Property Panel


Compile the class and restart the MethodServer

28
28
Exercise 3 : Code Snippets
@Override
public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException {
ComponentConfigFactory factory = getComponentConfigFactory();
PropertyPanelConfig propertyPanelConfig= factory.newPropertyPanelConfig();
propertyPanelConfig.setId("exercise3PropertyPanel");
// add properties
PropertyConfignameConfig= factory.newPropertyConfig();
nameConfig.setId("name");
propertyPanelConfig.addComponent(nameConfig);
PropertyConfigaddress1Config = factory.newPropertyConfig();
address1Config.setId("address1");
address1Config.setLabel("Address");
propertyPanelConfig.addComponent(address1Config);
MultiComponentConfig mconfig= new MultiComponentConfig();
// add the PropertyConfig
mconfig.addComponent(propertyPanelConfig);
// add a nested component
mconfig.addNestedComponent("exercise1");
// set the view
mconfig.setView("/custom/exercise3.jsp");
return mconfig;
}
29
29
Exercise 3 : Code Snippets
@Override
public Object buildComponentData(ComponentConfig config, ComponentParams params) throws WTException {

// data for the PropertyConfig


Map<String, String> address = new HashMap<String, String>();
address.put("name", "Parametric Technology Corp.");
address.put("address1", "3785 Pheasant Ridge Drive NE");
address.put("address2", "Blaine MN 55449");
address.put("country", "USA");
address.put("phone", "763-957-8000");
address.put("fax", "763-957-8001");
return address;
}

30
30
Exercise 3 : Code Snippets
// content of lab/exercise3.jsp
<%@ tagliburi="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>
<%@ tagliburi="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>
<%@include file="/netmarkets/jsp/util/begin_comp.jspf"%>
<%--render the property panel --%>
<jca:renderPropertyPanelcomponentDef="${exercise3PropertyPanel}" />
<%--register the listeners --%>
<script type="text/javascript">
PTC.onReady(function() {
Ext.ComponentMgr.onAvailable('exercise1', function(){
//register on renderTableEnd
this.on("renderTableEnd", function (){
alert("Data after renderTableEnd: " + this.getStore().getCount());
});
//register on dataSourceComplete
this.getStore().on("dataSourceComplete", function (){
alert("Data after dataSourceComplete: " + this.getCount());
});
});
});
</script>
<%--render the table --%>
<mvc:tablecompId="exercise1"/>
<%@ include file="/netmarkets/jsp/util/end_comp.jspf"%>

31
31
MVC Tree
A tree view is used to display hierarchical data organized in the form of a tree. In other words, a Tree is a visualization
of a hierarchy. In a tree structure, there are parent and child nodes. The hierarchy level is shown by indentation on the
left side of the Tree nodes. Implementing a Windchill Client Architecture tree is the same as implementing a Windchill
Client Architecture table. In tree, as opposed to specifying a service method or QuerySpec, a TreeHandler is specified
to populate the content.
Implementing a Tree Component using Asynchronous DataSource
To implement a tree component using Asynchronous DataSource, TreeDataBuilderAsync interface needs to be implemented. It has a single method
to be implemented by the concrete class : void buildNodeData(Object node, ComponentResultProcessor resultProcessor) throws Exception
The first call to this method from infrastructure will always pass first argument as
TreeNode.RootNode.This first call ensures that all rootNodes are fetched for subsequent calls. The
subsequent calls will always pass a treeNode for which child nodes are required to be fetched. An
example implementation code snippet is shown below
if (node == TreeNode.RootNode) {
nodes = getRootNodes();
resultProcessor.addElements(nodes);
}else {
getNodes(node);
nodes = resultProcessor.addElements(nodes); }

32
32
MVC Tree
To implement Tree component without DataSources, TreeHandler interface needs to be implemented. TreeHandler is a
JAVA interface, which is responsible for populating the tree content. TreeHandlerAdapter is an abstract class which
implements TreeHandler which should be extended, and the following methods should be implemented:
List<Object> getRootNodes() throws WTException {...}
Gets the list of root nodes for the tree
Map<Object, List> getNodes(List parents) throws WTException {...}
Get a mapping of the child nodes for each of the parent nodes in the given list.
TreeHandler has access to the ModelContext which can be used to access information, (eg OID), for the calling object
as shown in the psuedo code below
public List getRootNodes() throws WTException {
NmCommandBean cb = getModelContext().getNmCommandBean();
WTPart part;
NmOid oid = cb.getPageOid();
if ( oid != null && oid.isA(WTPart.class)) {
part = (WTPart)oid.getRef();
}

33
33
MVC Tree
setExpansionLevel
Set the initial expansion level of the tree
setNodeColumn
Set the name of the column that will be used to display
node labels
setShowTreeLines
Set whether tree lines will be displayed to show structure
in the tree
setDisableAction
If set to true, will not show the expand/collapse in the tree
See Javadoc and OOTB Examples,
(Customization>Componet Catalogue>Tree) for
further details

34
34
Exercise: Implementing Simple Tree

35
35

You might also like