JCA Components
These are few implementation of ComponentConfig :
• JcaTableConfig
• JcaTreeConfig
• JcaColumnConfig
• JcaInfoConfig
• JcaPropertyConfig
JCA Configurations for MVC
All the JCA specific Spring configurations are available in <Windchill>\codebase\config\mvc\jca-mvc.xml. The below snippet shows the configuration of url handler mapping. All the url pattern ptc1/comp/* are mapped to a bean with id componentController and the pattern ptc1/tcomp/* are mapped to a bean with id typeBasedComponentController.
<bean id="abstractComponentHandlerMapping" abstract="true"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
-----
</bean>
<bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping">
<property name="mappings" ref="componentHandlerMappings" />
-----
</bean>
<bean id="componentHandlerMappings"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties"><props>
<prop key="/comp/**">componentController</prop>
<prop key="/tcomp/**">typeBasedComponentController</prop>
</props></property>
</bean>
Below snippet shows the definition of the bean with componentController id.
• jcaComponentBuilderResolver is injected as theComponentBuilderResolver
• defaultViewMappings property is defined to map the default views
<bean id="componentController"
class="com.ptc.mvc.components.ComponentController">
<property name="componentBuilderResolver"
ref="jcaComponentBuilderResolver" />
<property name="defaultViewMappings">
<map>
<entry key="com.ptc.mvc.components.TreeConfig"
value="/components/tree.jsp" />
<entry key="com.ptc.mvc.components.TableConfig"
value="/components/table.jsp" />
<entry key="com.ptc.mvc.components.AttributesTableConfig“
value="/components/table.jsp" />
<entry key="com.ptc.mvc.components.AttributePanelConfig”
value="/components/attributePanel.jsp" />
</map>
</property>
-----------
</bean>
Below snippet shows the definition of the bean with typeBasedComponentController id.
• typeBasedComponentBuilderResolver is injected as the ComponentBuilderResolver. It respects the Windchill Type of the context object also while finding the best matched builder.
<bean id="typeBasedComponentController"
class="com.ptc.mvc.components.ComponentController“
parent="componentController“>
<property name="componentBuilderResolver"
ref="typeBasedComponentBuilderResolver" />
</bean>
The default handler specified will handle all the MVC url patterns that doesn’t have a mapping.
<bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping">
<property name="defaultHandler" ref="netmarketsController" />
-----
</bean>
<bean id="netmarketsController"
class="com.ptc.jca.mvc.controllers.LegacyController" />
ComponentConfigFactory
Builders which are ComponentConfigFactoryAware will be injected with a ComponentConfigFactory. ComponentConfigFactory provides instances of different implementations of ComponentConfig (eg table, tree etc). In JCA, the injection happens in the bean post processor and is configured in <Windchill>\codebase\config\mvc\jca-mvc.xml.
<bean class="com.ptc.mvc.components.support.ComponentBuilderBeanPostProcessor">
.....
<property name="componentConfigFactory" ref="jcaComponentConfigFactory" />
<property name="infoComponentConfigFactory">
......
</property>
<property name="typedAttrLayOutFactory">
<bean class="com.ptc.jca.mvc.components.JcaTypedAttrLayOutFactory" />
</property>
</bean>
<bean name="jcaComponentConfigFactory"
class="com.ptc.jca.mvc.components.JcaComponentConfigFactory"
factory-method="getInstance" />
ComponentDataConvertor
<bean id="jcaComponentDataConverter"
class="com.ptc.jca.mvc.components.JcaComponentDataConverter" />
<bean id="jcaComponentDataBuilder"
class="com.ptc.jca.mvc.components.DefaultJcaComponentDataBuilder"
scope="prototype">
<property name="componentDataConverter"
ref="jcaComponentDataConverter" />
</bean>
<bean id="jcaComponentBuilderResolver“
class="com.ptc.jca.mvc.components.JcaComponentBuilderResolver">
......
<lookup-method name="createJcaDataBuilder"
bean="jcaComponentDataBuilder" />
</bean>
The data that is available from the ComponentDataBuilder need to be processed so that it can be consumed by JCA. Running the data thorough the dataUtilities happen in this stage. JcaComponentDataConverter does that and is injected into the jcaComponentBuilderResolver.
ComponentBuilder Resolver
• If the DataBuilder specified is an instance of ConvertingComponentDataBuilder, JcaComponentBuilderResolver uses that as the ComponentDataBuilder.
• If the DataBuilder specified is an instance of ComponentDataBuilder, JcaComponentBuilderResolver uses that as the internal builder for the DefaultJcaComponentDataBuilder.
Generate MVC URLs
There are two types of JCA MVC urls.
• Non TypeBased JCA MVC url : Here the context object doesn’t participate in the builder resolution process.
• TypeBased JCA MVC url : Here the context object’s type participate in the builder resolution process.
This is generated using action definition
<action>
<component name="myCompId" ……/>
</action>
<action>
<component name="myCompId" " typeBased="true" ……/>
</action>
e.g
<action name="CustEx_mvc_table">
<component name="carambola.mvc.table" windowType="page" />
</action>
<action name="primaryAttributes" resourceBundle="com.ptc.core.ui.navigationRB">
<component name="primaryAttributes" typeBased="true" windowType="page"/>
---
</action>
<Windchill>/codebase/ WEB-INF/tlds/mvc.tld has helper functions that can be used
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%>
---
<jsp:include page="${mvc:getComponentURL('part.report.multiLevelBOM')}" />
-----
Table Size Limit
The maximum number of rows displayed in a table is driven by this preference which has a USER level visibility. It will be applicable to all the JCA tables in the system. Currently the OOTB default value is 2,000 rows and you can vary it based on client hardware and browser type.
For trees, the limit is enforced but can be overridden by the end users. Once the tree reaches the size limit, collapse of any node will remove its children from the client, to free some resource in the client. This will happen till the number of nodes in the client comes below the size limit.
Action Handling
Actions can be broadly divided into three groups.
These actions can be performed once your objects are loaded.
• Group 1 – Actions which act only on loaded data
◦ Row-level and multi-select actions
◦ Select all, Ctrl/Shift select, Clear all
◦ View selected objects only
• Group 2 – Actions which act on the entire data set
These actions can be performed anytime (If incomplete data set, goes to the server to get all the data)
◦ Switching table views
◦ Search in table
◦ Export list
• Group 3 – Actions which apply to the table itself
These actions can be performed anytime
◦ Create actions
◦ Cancel data loading
◦ Save table view
Sorting
Sorting is a special action and with DataSource, depends on the data in the client.
• If complete data set
◦ Sorting happen in the client
• If data still loading
◦ Sorting happen on the data already in the client
◦ Insert remaining polling rows into the client in sorted order
• If results limit was reached
◦ Sorting happen in the client
◦ Only the rows that are in the client are sorted (not the complete data set)
• Version column is an exception, which makes a server trip to do the sorting, but only on the data set available in the client.
Tips
Enabling Spring Logging
Please add the following entry in <Windchill>\codebase\WEB-INF\log4jMethodServer.properties and restart the server.
logger.Springframework.name=org.springframework
logger.Springframework.level=DEBUG
Accessing Localized Messages
ResourceBundleClientMessageSource can be used to get the localized messages.
String resourceBundle = "com.ptc.test.TestResource";
ClientMessageSource messageSource =
new ResourceBundleClientMessageSource(resourceBundle);
String message = messageSource.getMessage(TestResource.TEST);
Entry in the TestResource file
@RBEntry("Test Message")
public static final String TEST = "test";
If your builder extends OOTB abstract builders, take advantage of its api
AbstractComponentConfigBuilder.getMessageSource(String resourceBundle)
AbstractComponentDataBuilder.getMessageSource(String resourceBundle)
AbstractInfoConfigBuilder.getMessageSource(String resourceBundle)
Accessing Localized Messages
Storing View Components
All the view jsps will be placed under <Windchill>\WEB-INF\jsp and the value you specify while specifying it should be relative to <Windchill>\WEB-INF\jsp.
table.setView("/carambola/carambolaMVCExampleTable.jsp");
Requesting the Nm*Bean in JCA Component Builders
NmHelperBean helper = ((JcaComponentParams) params).getHelperBean();
NmCommandBean nmCommandBean = helper.getNmCommandBean();
HttpServletRequest request = nmCommandBean.getRequest();
Thread Safety of Builders
By default the builders follow the thread safety paradigm of servlets (Singleton scope), meaning that instance variables in your builders must be thread-safe. Communication between your config and data builder APIs can be done through either the config object itself, or via ComponentParams.
public class TestComponentBuilder extends AbstractComponentBuilder{
@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
Object myObject;
//add information that you want to pass to data builder
params.setAttribute("myKey", myObject);
-----
}
@Override
public Object buildComponentData(ComponentConfig config,
ComponentParams params)
throws WTException {
//get the information that was put in config builder
Object myObject = params.getAttribute("myKey");
-----
}
}