# User Defined Java Class

## ![](/files/nQwhfRlbL1OwDsAZI30i) User Defined Java Class

### Description <a href="#description" id="description"></a>

The User Defined Java Class transform allows you to enter User Defined Java Class to drive the functionality of a complete transform.

In essence, this transform allows you to program your own plugin in a transform.

The goal of this transform is not to allow a user to do full-scale Java development inside a transform.

Obviously we have a whole plugin system available to help with that part.

The goal is to allow users to define methods and logic with as little as code as possible, executed as fast as possible.

For this we use the [Janino](https://janino-compiler.github.io/janino/) project libraries that compile Java code in the form of classes at runtime.

| Hop Engine | <sup>✓</sup> |
| ---------- | ------------ |
| Spark      | ?            |
| Flink      | ?            |
| Dataflow   | ?            |

### Options

| Option            | Description                                                                                                                                                                                                                                                  |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Transform name    | Name of the transform.                                                                                                                                                                                                                                       |
| Class code        | The Java code.                                                                                                                                                                                                                                               |
| Fields            | <p>List of output fields.</p><ul><li>Fieldname: Output field name.</li><li>Type: Type of field.</li><li>Length: Length of the field.</li><li>Precision: Precision of the field.</li></ul>                                                                    |
| Parameters        | <p>You can use the Parameters table to avoid using hard-coded string values, such as field names (customer for example).</p><ul><li>Tag: The parameter tag.</li><li>Value: The parameter value.</li><li>Description: Description of the parameter.</li></ul> |
| Info transforms   | <p>Additional transforms to read data from</p><ul><li>Tag</li><li>Transform: Which transform to read from.</li><li>Description</li></ul>                                                                                                                     |
| Target transforms | <p>Destination Transform</p><ul><li>Tag</li><li>Transform: Which transform to output to.</li><li>Description</li></ul>                                                                                                                                       |
| Test class        | Tests the class.                                                                                                                                                                                                                                             |

### Usage

#### Process rows

The Processor code defines the processRow() method, which is the heart of the transform. This method is called by the pipeline in a tight loop and will continue until false is returned.

```highlight
String firstnameField;
String lastnameField;
String nameField;

public boolean processRow() throws HopException
{
    // 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 transform.
    //
    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;
```

#### Error handling

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

```highlight
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 transform 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 transform in the sample pipeline. The ErrorPath transform is also specified in the Target transforms tab of the User Define Java Class transform.

#### Logging

You need to implement logging in your defined transform if you want Hop 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:

```highlight
putRow( data.outputMeta, r );

if ( checkFeedback( getLinesOutput() ) ) {
  if ( log.isBasic() ) {
    logBasic( "Have I got rows for you! " + getLinesOutput() );
  }
}
```

#### 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 Hop code related to the User Defined Java Class transform. 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.

```highlight
IRowMeta 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.

```highlight
IValueMeta 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 pipeline, you could look up field names in advance in a first block of code, as shown in the following example:

```highlight
if (first) {
 yearIndex = getInputRowMeta().indexOfValue(getParameter("YEAR"));
 if (yearIndex<0) {
   throw new HopException("Year field not found in the input row, check parameter 'YEAR'\!");
 }
}
```

To get the Integer value contained in the year field, you can then use the following construct.

```highlight
Object[] r = getRow();
...
Long year = inputRowMeta().getInteger(r, yearIndex);
```

To make this process easier, you can use a shortcut in the following form.

```highlight
Long year = get(Fields.In, "year").getInteger(r);
```

This method also takes into account the index-based optimization mentioned above.

### Blocking specific code

As a simple security measure you can block the execution of code containing specific strings. This can be done by adding exclusions to the `codeExclusions.xml` file located at \<Hop Installation>/plugins/transforms/janino

Example:

```highlight
    <exclusions>
        <exclusion>System.</exclusion>
        <exclusion>HopVfs.</exclusion>
    </exclusions>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.primeur.com/data-shaper-1.21/knowing-the-data-shaper-designer/pipelines/transforms/userdefinedjavaclass.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
