Advanced Customization > Windchill Adapter > Custom Windchill Adapter Webjects > Hello-World Example
  
Hello-World Example
The following example steps take you through the process of creating a new type-aware Hello-World webject delegate. The webject creates an output group based on an input group, and optionally echoes some “Hello World” messages to an output java.io.PrintWriter.
Step 1: Write the new webject delegate
Since the Hello-World webject is not actually interacting with Windchill business objects and is not going to make use of any convenience methods provided by the Windchill adapter base classes, it simply needs to implement com.ptc.core.adapter.server.impl.TypeAwareWebjectDelegate.
* 
This example is most effective if you read through the source for this webject.
The webject source can be found under:
<Windchill>/prog_examples/adapter/windchill/customwebjects/src
Step 2: Inform the Windchill adapter of the new webject
In order for the Windchill adapter to be able to recognize the new webject delegate, it must be registered in wt.adapter.delegates.properties.
Add the following line:
HELLOWORLD.WCTYPE|
java.lang.Object=ext.example.HelloWorldWebjectDelegate
This entry specifies the name of the new webject delegate, HELLOWORLD, and it indicates that the webject is valid for target objects of class or type java.lang.Object. Finally, it indicates which class contains the invoke() method that should be executed.
You must restart the method server for this change to be recognized.
Step 3: Create an XML task
Now, create an XML task document containing a Hello-World webject. You must create the task within the tasks directory that was set up for your Windchill server. The following is an example Hello-World.xml:
* 
The task source can be found in your installation at:
<Windchill>/prog_examples/adapter/windchill/customwebjects/tasks
<%@page language="java"%>

<%@taglib uri="http://www.ptc.com/infoengine/taglib/core" prefix="ie"%>



<!--com.infoengine.soap.rpc.def

This task simply invokes the Hello-World example adapter webject delegate
with generic input.

@return INFOENGINE_GROUP ${helloWorldResults}

-->

<ie:webject name="Create-Group" type="GRP">
<ie:param name="ELEMENT" data="a=b:b=c:c=d"/>
<ie:param name="ELEMENT" data="a=b1:b=c1:c=d1"/>
<ie:param name="ELEMENT" data="a=b2:b=c2:c=d2"/>
<ie:param name="ELEMENT" data="a=b3:b=c3:c=d3"/>
<ie:param name="GROUP_OUT" data="helloInput"/>
</ie:webject>

<ie:webject name="Hello-World" type="ACT">
<ie:param name="INSTANCE" data="$(@FORM[]supporting-adapter[*])"
delim="!" valueSeparator="!"
default="<%=com.infoengine.au.NamingService.getVMName(
)%>"/>
<ie:param name="GROUP_IN" data="helloInput" />
<ie:param name="GROUP_OUT" data="helloWorldResults" />
<ie:param name="HELLO_WHERE" data="out" />
<ie:param name="HELLO_WORLD" data="bob,steve,fred"
delim=","/>
<ie:param name="START" data="1" />
<ie:param name="STOP" data="2" />
</ie:webject>
Step 4: Test the new webject delegate
To test the webject, execute the following URL:
http://<yourIEServer>/<IEAlias>/Hello-World.xml
<yourIEServer> is the name of the server on which you are running the Info*Engine servlet.
<IEAlias> is the name of the servlet alias set up for Info*Engine tasks.
For example:
http://host.company.com/Windchill/servlet/IE/tasks/ext/example/HelloWorld.xml
The output returned from this URL is similar to the following:
<?xml version="1.0" encoding="UTF-8"?>
<wc:COLLECTION xmlns:wc="http://www.ptc.com/infoengine/1.0">
<Unknown-Class-Name
NAME="helloWorldResults"
TYPE="Unknown" STATUS="0">
<wc:INSTANCE>
<a>b1</a>
<b>c1</b>
<c>d1</c>
</wc:INSTANCE>
<wc:INSTANCE>
<a>b2</a>
<b>c2</b>
<c>d2</c>
</wc:INSTANCE>
</Unknown-Class-Name>
</wc:COLLECTION>
This example hard codes all the parameter values.
Using Info*Engine ParameterDef Annotations
ParameterDef annotations have the following default values:
The default for type is String, meaning there is no need to specify type if the parameter is a string.
The default for minValues is 0
minValues determines whether the parameter is required. A value of greater than 0 indicates that the parameter is required.
The default for maxValues is 1.
maxValues determines whether an array is returned when using Webject.objectParamValue.
If the value is less than or equal to 0, the parameter is multi-valued and unbounded. Calling Webject.objectParamValue for a parameter defined this way results in an array being returned containing zero or more objects with no limitation on how many objects can be returned.
If the value is 1, this means the parameter is single-valued (this is the default) and an array is not be returned.
If the value is greater than 1, the parameter is multi-valued, but the user can specify no more than maxValues parameters. Specifying minValues in conjunction decides how many the user must supply (0 meaning optional)
The default for defaultValue is "" which is equated to null at runtime
* 
If a single-valued parameter is not specified, null will be returned. This is why defaults are important for data types like Boolean, Integer, and so on. If the default values are not there, you must check for null and cannot simply cast the results into your variable. Logical default values for parameters are always a good idea.
The following are some additional points of interest when using ParameterDef annotations:
If a multi-valued parameter is optional and not specified, an empty array is returned. This is inconsistent with the null of single-valued parameters, but is done for convenience purposes to avoid having to explicitly check for null when performing iteration on multi-valued parameters.
Interdependent attributes are validated in webject.validate (these attributes are discussed below).
The values of minValues and maxValues are validated in webject.validate.
If for example, you require two GROUP_IN parameters, then you would set minValues="2" and maxValues="2". When gathering the groups, you might do something such as "Group [ ] grps = (Group [ ])webject.objectParamValue ( "GROUP_IN" )".
As a result, the grps array has a length of two and contains the groups specified on the webject. If more or less than two GROUP_IN parameters are supplied, an exception would be raised. If any of the specified GROUP_IN parameters referenced a group not found in the VDB, then an exception would be also be thrown.
* 
If you are extending one of the supplied base classes and are overriding a parameter gathered by a parent class, then you must not change the type or cardinality or the parameter.
Since adapter webjects make use of a parameter named GROUP_IN, which is single valued, you cannot make that parameter an array (as mentioned above). If you need such a parameter in a webject that extends one of the common adapter base classes, then you should give the parameter a unique name.
The following are some additional ParameterDef attributes:
interdependent—A string of interdependent parameter names.
select—A string of mutually-exclusive parameter names.
exampleValue—Used for documentation purposes only.
ParameterDef Example
...
@ParameterDef(name="TYPE",interdependent={"WHERE"},select=
{"OBJECT_REF"},description="The business object type."),
@ParameterDef(name="WHERE,maxValues=-1,interdependent={"TYPE"},
select={"OBJECT_REF"},description ="The where clause(s)."),
@ParameterDef(name="OBJECT_REF",maxValues=-1,
select={"TYPE","WHERE"},description="The ufid(s).",exampleValue="ufid")
...
In the above example an error would occur on validate if:
Either TYPE or WHERE were specified but not both (the parameters are dependent on one another).
OBJECT_REF was specified and either TYPE or WHERE was specified (the TYPE and WHERE parameters are defined as mutually exclusive to OBJECT_REF).
* 
When using these annotations in a hierarchy:
Sub-classes override ParameterDefs found within super-classes.
These annotations are supported within interfaces as well, so you can inherit parameter definitions from shared interfaces.
As it pertains to Windchill webjects and AbstractWebject in particular, you need to be very careful when overriding parameters. When extending a common adapter base class (ObjectWebject, ActionWebject or AbstractWebject) you should never change a parameter’s type, cardinality, or remove its defaultValue.
If you do so you are almost sure to introduce a bug for your webject, since those base classes are coded based on their own annotations and have no knowledge of extending class annotations.