Multi-port transformers
Adding an input port
Note
This functionality is new to FME 2024 and requires fmetools>=0.9.0.
By default, transformers have a single input port. Here are the steps to add another input port to a transformer:
- Open the transformer definition FMXJ in FME Transformer Designer.
-
Rename the original input port by selecting the port and editing its Configuration. By default, the original input port has no identifier, but an Execution Template Identifier is required when adding additional input ports.
Setting Value Execution Instance Identifier Execution Template Identifier Input1
Display Name Input1
Description First input port Note
The Execution Instance Identifier must be left blank for all input ports, as required by the TeeFactory.
-
Add a new input port using the
Port
button from the top menu and selectingInput
. -
Edit the new input port's Configuration:
Setting Value Execution Instance Identifier Execution Template Identifier Input2
Display Name Input2
Description Second input port -
Open the Execution Instructions pane from the View menu.
-
In the execution instructions, edit the original TeeFactory so that it only handles features from
Input1
.Execution Instructions# Put config values onto input feature from `Input1` as internal-prefixed attributes. FACTORY_DEF {*} TeeFactory FACTORY_NAME { $(XFORMER_NAME)_Input1_CATCHER } $(INPUT_Input1_LINES) OUTPUT { FEATURE_TYPE $(XFORMER_NAME)_Input1_READY @SupplyAttributes(___XF_VERSION, 1) $(FME_PARM_VAL_LIST) }
Note
@SupplyAttributes(___XF_VERSION, 1)
is required for usage of TransformerParameterParser. For information on parameter parsing, refer to the Hello World guide. -
Add another TeeFactory that handles features from
Input2
.Execution Instructions# Put config values onto input feature from `Input1` as internal-prefixed attributes. FACTORY_DEF {*} TeeFactory FACTORY_NAME { $(XFORMER_NAME)_Input1_CATCHER } $(INPUT_Input1_LINES) OUTPUT { FEATURE_TYPE $(XFORMER_NAME)_Input1_READY @SupplyAttributes(___XF_VERSION, 1) $(FME_PARM_VAL_LIST) } # Put config values onto input feature from `Input2` as internal-prefixed attributes. FACTORY_DEF {*} TeeFactory FACTORY_NAME { $(XFORMER_NAME)_Input2_CATCHER } $(INPUT_Input2_LINES) OUTPUT { FEATURE_TYPE $(XFORMER_NAME)_Input2_READY @SupplyAttributes(___XF_VERSION, 1) $(FME_PARM_VAL_LIST) }
- Update the PythonFactory to handle input coming from both TeeFactories.
Execution Instructions
# Pass input feature to Python. # Remove all internal-prefixed attributes before emitting feature # through the correct output port. FACTORY_DEF {*} PythonFactory FACTORY_NAME { $(XFORMER_NAME) } INPUT { Input1 FEATURE_TYPE $(XFORMER_NAME)_Input1_READY } INPUT { Input2 FEATURE_TYPE $(XFORMER_NAME)_Input2_READY } SYMBOL_NAME fme_demogreeter.transformer.TransformerImpl PY_OUTPUT_TAGS { Output <Rejected> } OUTPUT { Output FEATURE_TYPE $(OUTPUT_Output_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_Output_FUNCS) } OUTPUT { <Rejected> FEATURE_TYPE $(OUTPUT_<Rejected>_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_<Rejected>_FUNCS) }
- In the PythonFactory, add a
PY_INPUT_TAGS
clause. For more information on thePY_INPUT_TAGS
clause, refer to the PythonFactory section in the FME Factory and Function Documentation.Execution Instructions# Pass input feature to Python. # Remove all internal-prefixed attributes before emitting feature # through the correct output port. FACTORY_DEF {*} PythonFactory FACTORY_NAME { $(XFORMER_NAME) } PY_INPUT_TAGS { Input1 Input2 } INPUT { Input1 FEATURE_TYPE $(XFORMER_NAME)_Input1_READY } INPUT { Input2 FEATURE_TYPE $(XFORMER_NAME)_Input2_READY } SYMBOL_NAME fme_demogreeter.transformer.TransformerImpl PY_OUTPUT_TAGS { Output <Rejected> } OUTPUT { Output FEATURE_TYPE $(OUTPUT_Output_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_Output_FUNCS) } OUTPUT { <Rejected> FEATURE_TYPE $(OUTPUT_<Rejected>_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_<Rejected>_FUNCS) }
-
A transformer with multiple input ports will need to use a different set of Python methods than a transformer with a single input port. These methods are available in the
FMEEnhancedTransformer
. An example of a Python transformer implementation for a single input port can be found in the Python transformer implementation section in the Hello World guide. This example can be updated to handle multiple input ports by usingsetup_from()
andreceive_feature_from()
:For more information, refer to the FMEEnhancedTransformer documentation.class TransformerImpl(FMEEnhancedTransformer): """ The Python implementation of the DemoGreeter transformer, updated to handle multiple input ports. Each instance of the transformer in the workspace has an instance of this class. """ params: TransformerParameterParser version: int def setup_from(self, first_feature: FMEFeature, input_tag: str): """ Initialization steps based the first feature received by the transformer. """ super().setup_from(first_feature, input_tag) # Get transformer version from internal attribute on first feature, # and load its parameter definitions. # Note: TransformerParameterParser requires >=b24145 when running on FME Flow. self.version = int(first_feature.getAttribute("___XF_VERSION")) self.params = TransformerParameterParser( "example.my-package.DemoGreeter", version=self.version, ) def receive_feature_from(self, feature: FMEFeature, input_tag: str): # Pass internal attributes on feature into parameter parser. # Then get the parsed value of the First Name parameter. # By default, these methods assume a prefix of '___XF_'. self.params.set_all(feature) first_name = self.params.get("FIRST_NAME") # Set the output attributes, and output the feature. feature.setAttribute("_greeting", "Hello, {}!".format(first_name)) feature.setAttribute("_input_tag", input_tag) # For this demo self.pyoutput(feature)
Adding an output port
Note
This functionality is new to FME 2024 and requires fmetools>=0.8.0.
By default, transformers generated with the FME Transformer Designer have two output ports: a standard Output
port and
a <Rejected>
port. Here are the steps to add another output port to a transformer:
- Open the transformer definition FMXJ in FME Transformer Designer.
- Add a new output port using the
Port
button from the top menu and selectingOutput
. -
Edit the new output port's Configuration:
Setting Value Execution Instance Identifier Output2
Display Name Output2
Description Another output port -
Open the Execution Instructions pane from the View menu.
- In the execution instructions, update the PythonFactory's
PY_OUTPUT_TAGS
clause to include the new output tag. For more information on thePY_OUTPUT_TAGS
clause, refer to the PythonFactory section in the FME Factory and Function Documentation.Execution Instructions# Pass input feature to Python. # Remove all internal-prefixed attributes before emitting feature # through the correct output port. FACTORY_DEF {*} PythonFactory FACTORY_NAME { $(XFORMER_NAME) } INPUT { FEATURE_TYPE $(XFORMER_NAME)_READY } SYMBOL_NAME fme_demogreeter.transformer.TransformerImpl PY_OUTPUT_TAGS { Output Output2 <Rejected> } OUTPUT { Output FEATURE_TYPE $(OUTPUT_Output_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_Output_FUNCS) } OUTPUT { <Rejected> FEATURE_TYPE $(OUTPUT_<Rejected>_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_<Rejected>_FUNCS) }
- In the same PythonFactory, add an
OUTPUT
clause for the new output tag.Execution Instructions# Pass input feature to Python. # Remove all internal-prefixed attributes before emitting feature # through the correct output port. FACTORY_DEF {*} PythonFactory FACTORY_NAME { $(XFORMER_NAME) } INPUT { FEATURE_TYPE $(XFORMER_NAME)_READY } SYMBOL_NAME fme_demogreeter.transformer.TransformerImpl PY_OUTPUT_TAGS { Output Output2 <Rejected> } OUTPUT { Output FEATURE_TYPE $(OUTPUT_Output_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_Output_FUNCS) } OUTPUT { Output2 FEATURE_TYPE $(OUTPUT_Output2_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_Output2_FUNCS) } OUTPUT { <Rejected> FEATURE_TYPE $(OUTPUT_<Rejected>_FTYPE) @RemoveAttributes(fme_regexp_match,^___XF_.*$) $(OUTPUT_<Rejected>_FUNCS) }
-
To output features from the new output port, use
.pyoutput(feature, output_tag="Output2")
in the Python transformer implementation. For more information on.pyoutput
, refer to the pyoutput documentation.