Java list contains user defined object

User Defined Java Class

  1. Last updated
  2. Save as PDF
  1. Not complete Java
  2. General [User Defined Java Class]
    1. Class Code [User Defined Java Class]
      1. Process rows
      2. Error handling
      3. Logging
    2. Class and code fragments
  3. Options
    1. Fields tab
    2. Parameters tab
    3. Info steps tab
    4. Target steps tab
  4. Examples
  5. Metadata injection support

You can use the User Defined Java Class step to enter your own Java class to drive the functionality of a complete step. You can program your own plugin into a step, yet the goal of this step is not to do full-scale Java development inside of a step. A whole plugin system is available to help with that part [see Embed and extend PDI functionality]. The goal is for you to just define Java methods and logic. For this step, the Janino project libraries are used to compile Java code in the form of classes at runtime.

Parent Topic
  • Products
Child Topics
  • Not complete Java
  • General [User Defined Java Class]
  • Options
  • Examples
  • Metadata injection support

Not complete Java

Janino and this step do not need the complete Java class. It only needs the class body [such as the imports, constructors, and methods]. The step does not need the full class declaration. This step was designed with this approach, over the definition of the full class, to hide technical details and methods for ease of use.

You enter your main code into the Processor, which defines the processRow[] method. In PDI, the following imports are already a part of the Processor code:

  • org.pentaho.di.trans.steps.userdefinedjavaclass.*
  • org.pentaho.di.trans.step.*
  • org.pentaho.di.core.row.*
  • org.pentaho.di.core.*
  • org.pentaho.di.core.exception.*

The imports listed above are only a part of the Processor code. They are not a part of any code blocks you might enter into additional Class code tabs.

If you need to add other imports to your Processor code, include them at the very top of the code you will create for this step, as shown in the following example:

import java.util.*;

Janino, essentially a Java complier, only supports a sub-set of the Java 1.8.x specification. To see a complete list of the features and limitations, see the Janino homepage.

Parent Topic
  • User Defined Java Class

General [User Defined Java Class]

Enter the following information in the transformation step name field.

  • Step name: Specifies the unique name of the transformation step on the canvas. The step name is set to User Defined Java Class by default.

Use the Class code panel and the option tabs to enter your defined Java class. After you specify your Java class, you click Test class to test it.

Parent Topic
  • User Defined Java Class
Child Topics
  • Class Code [User Defined Java Class]
  • Class and code fragments

Class Code [User Defined Java Class]

Add your defined Java code directly in the Processor tab in the Class code panel. You can create additional tabs for more code blocks by right-clicking and selecting Add new. This menu also includes options for copying a tab, setting a transformation class, or removing a class type.

Parent Topic
  • General [User Defined Java Class]
Child Topics
  • Process rows
  • Error handling
  • Logging

Process rows

The Processor code defines the processRow[] method, which is the heart of the step. This method is called by the transformation in a tight loop and will continue until false is returned.

NotegetRow[] method must be called before the first get[Fieds.in, FIELD_NAME] that helps to avoid situations with unexpected fields ordering in the data obtained from the previous step [such as Mapping input specification].

A very simple example that calculates firstname+" "+lastname and stores it into a nameField is shown in the following example Processor code block:

String firstnameField; String lastnameField; String nameField; public boolean processRow[StepMetaInterface smi, StepDataInterface sdi] throws KettleException { // Let's look up parameters only once for performance reason. // if [first] { firstnameField = getParameter["FIRSTNAME_FIELD"]; lastnameField = getParameter["LASTNAME_FIELD"]; nameField = getParameter["NAME_FIELD"]; first=false; } // First, get a row from the default input hop // Object[] r = getRow[]; // If the row object is null, we are done processing. // if [r == null] { setOutputDone[]; return false; } // It is always safest to call createOutputRow[] to ensure that your output row's Object[] is large // enough to handle any new fields you are creating in this step. // Object[] outputRow = createOutputRow[r, data.outputRowMeta.size[]]; String firstname = get[Fields.In, firstnameField].getString[r]; String lastname = get[Fields.In, lastnameField].getString[r]; // Set the value in the output field // String name = firstname+" "+lastname; get[Fields.Out, nameField].setValue[outputRow, name]; // putRow will send the row on to the default output hop. // putRow[data.outputRowMeta, outputRow]; return true;
Parent Topic
  • Class Code [User Defined Java Class]

Error handling

If you want PDI to handle errors that may occur while running your class in a transformation, you must implement for your own error handling code. Before adding any error handling code, right-click on the User Defined Java Class step in the PDI client canvas and select Error Handling in the menu that appears. The resulting Step error handling settings dialog box contains options for specifying an error target step and associated field names that you will use to implement error handling in your defined code.

The following try code block from the User Defined Java Class Lambda Examples.ktr in the data-intregation/samples/transformations directory contains an example of such error handling:

try { Object numList = strsList.stream[] .map[ new ToInteger[] ] .sorted[ new ReverseCase[] ] .collect[ Collectors.toList[] ]; get[ Fields.Out, "reverseOrder" ].setValue[ row, numList.toString[] ]; } catch [NumberFormatException ex] { // Number List contains a value that cannot be converteds to an Integer. rowInError = true; errMsg = ex.getMessage[]; errCnt = errCnt + 1; } if [ !rowInError ] { putRow[ data.outputRowMeta, row ]; } else { // Output errors to the error hop. Right click on step and choose "Error Handling..." putError[data.outputRowMeta, row, errCnt, errMsg, "Not allowed", "DEC_0"]; }

The try in the code sample above tests to see if numList contains valid numbers. If the list contains a number that is not valid, putError is used to handle the error and direct it to the wlog: ErrorPath step in the sample transformation. The ErrorPath step is also specified in the Target steps tab of the User Define Java Class step.

Parent Topic
  • Class Code [User Defined Java Class]

Logging

You need to implement logging in your defined step if you want PDI to log data actions from your class, such as read, write, output, or update data. The following code is an example of how to implement logging:

putRow[ data.outputMeta, r ]; if [ checkFeedback[ getLinesOutput[] ] ] { if [ log.isBasic[] ] { logBasic[ "Have I got rows for you! " + getLinesOutput[] ]; } }
Parent Topic
  • Class Code [User Defined Java Class]

Class and code fragments

You can navigate through your defined classes along with related code snippets and fields through the Classes and Code Fragments panel. You can right-click on any item in this tree to either Delete, Rename, or Show Sample.

Classes

The Classes folder indicates what classes have corresponding code block tabs in the Class Code panel.

Code Snippits

The Code Snippits folder shows the internal PDI code related to the User Defined Java Class step. These snippits are shown as reference for the code of your class.

Input Fields

The Input fields folder contains any input fields you define in your code. While working with your defined code, you will be handling input and output fields. Many ways exist for handling input fields. For example, to start, examine the following description of an input row:

RowMetaInterface inputRowMeta = getInputRowMeta[];

The inputRowMeta object contains the metadata of the input row. It includes all the fields, their data types, lengths, names, format masks, and more. You can use this object to look up input fields. For example, if you want to look for a field called customer, you would use the following code:

ValueMetaInterface customer = inputRowMeta.searchValueMeta["year"];

Because looking up field names can be slow if you need to do it for every row that passes through a transformation, you could look up field names in advance in a first block of code, as shown in the following example:

if [first] { yearIndex = getInputRowMeta[].indexOfValue[getParameter["YEAR"]]; if [yearIndex

Chủ Đề