CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-plc4x--plc4j-api

Central API Module providing core interfaces and abstractions for unified access to industrial programmable logic controllers (PLCs)

Pending
Overview
Eval results
Files

exception-handling.mddocs/

Exception Handling

Comprehensive exception hierarchy for robust error handling in industrial communication with Apache PLC4X Java API.

Exception Hierarchy

Base Exception Classes

/**
 * Base checked exception for all PLC4X operations
 */
public class PlcException extends Exception {
    /**
     * Create exception with message
     * @param message Error description
     */
    public PlcException(String message);
    
    /**
     * Create exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcException(String message, Throwable cause);
    
    /**
     * Create exception with cause
     * @param cause Underlying cause
     */
    public PlcException(Throwable cause);
    
    /**
     * Create exception with full control over suppression and stack trace
     * @param message Error description
     * @param cause Underlying cause
     * @param enableSuppression Whether suppression is enabled
     * @param writableStackTrace Whether stack trace is writable
     */
    public PlcException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace);
}

/**
 * Base runtime exception for all PLC4X operations
 */
public class PlcRuntimeException extends RuntimeException {
    /**
     * Create runtime exception with message
     * @param message Error description
     */
    public PlcRuntimeException(String message);
    
    /**
     * Create runtime exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcRuntimeException(String message, Throwable cause);
    
    /**
     * Create runtime exception with cause
     * @param cause Underlying cause
     */
    public PlcRuntimeException(Throwable cause);
}

Connection-Related Exceptions

PlcConnectionException

/**
 * Exception thrown when connection operations fail
 */
public class PlcConnectionException extends PlcException {
    /**
     * Create connection exception with message
     * @param message Error description
     */
    public PlcConnectionException(String message);
    
    /**
     * Create connection exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcConnectionException(String message, Throwable cause);
    
    /**
     * Create connection exception with cause
     * @param cause Underlying cause
     */
    public PlcConnectionException(Throwable cause);
    
    /**
     * Create connection exception with full control over suppression and stack trace
     * @param message Error description
     * @param cause Underlying cause
     * @param enableSuppression Whether suppression is enabled
     * @param writableStackTrace Whether stack trace is writable
     */
    public PlcConnectionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace);
}

Common Causes:

  • Network connectivity issues
  • Invalid connection URLs
  • Authentication failures
  • PLC not responding
  • Protocol negotiation failures

I/O Related Exceptions

PlcIoException

/**
 * Exception thrown when I/O operations fail
 */
public class PlcIoException extends PlcException {
    /**
     * Create I/O exception with message
     * @param message Error description
     */
    public PlcIoException(String message);
    
    /**
     * Create I/O exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcIoException(String message, Throwable cause);
}

Common Causes:

  • Network timeouts
  • Socket errors
  • Communication interruptions
  • Buffer overflows
  • Serialization/deserialization errors

Protocol-Related Exceptions

PlcProtocolException

/**
 * Exception thrown when protocol-level errors occur
 */
public class PlcProtocolException extends PlcException {
    /**
     * Create protocol exception with message
     * @param message Error description
     */
    public PlcProtocolException(String message);
    
    /**
     * Create protocol exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcProtocolException(String message, Throwable cause);
}

PlcProtocolTimeoutException

/**
 * Exception thrown when protocol operations timeout
 */
public class PlcProtocolTimeoutException extends PlcProtocolException {
    /**
     * Create protocol timeout exception with message
     * @param message Error description
     */
    public PlcProtocolTimeoutException(String message);
}

PlcProtocolPayloadTooBigException

/**
 * Exception thrown when protocol payload exceeds size limits
 */
public class PlcProtocolPayloadTooBigException extends PlcProtocolException {
    /**
     * Create payload too big exception with message
     * @param message Error description
     */
    public PlcProtocolPayloadTooBigException(String message);
}

Timeout Exceptions

PlcTimeoutException

/**
 * Exception thrown when operations timeout
 */
public class PlcTimeoutException extends PlcException {
    /**
     * Create timeout exception with message
     * @param message Error description
     */
    public PlcTimeoutException(String message);
    
    /**
     * Create timeout exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcTimeoutException(String message, Throwable cause);
}

Feature Support Exceptions

PlcNotImplementedException

/**
 * Exception thrown when requested feature is not implemented
 */
public class PlcNotImplementedException extends PlcException {
    /**
     * Create not implemented exception with message
     * @param message Error description
     */
    public PlcNotImplementedException(String message);
}

PlcUnsupportedOperationException

/**
 * Exception thrown when operation is not supported by the driver/protocol
 */
public class PlcUnsupportedOperationException extends PlcException {
    /**
     * Create unsupported operation exception with message
     * @param message Error description
     */
    public PlcUnsupportedOperationException(String message);
}

PlcUnsupportedDataTypeException

/**
 * Exception thrown when data type is not supported
 */
public class PlcUnsupportedDataTypeException extends PlcException {
    /**
     * Create unsupported data type exception with message
     * @param message Error description
     */
    public PlcUnsupportedDataTypeException(String message);
}

PlcUnsupportedProtocolException

/**
 * Exception thrown when protocol is not supported
 */
public class PlcUnsupportedProtocolException extends PlcConnectionException {
    /**
     * Create unsupported protocol exception with message
     * @param message Error description
     */
    public PlcUnsupportedProtocolException(String message);
}

Tag-Related Exceptions

PlcInvalidTagException

/**
 * Exception thrown when tag address is invalid
 */
public class PlcInvalidTagException extends PlcException {
    /**
     * Create invalid tag exception with message
     * @param message Error description
     */
    public PlcInvalidTagException(String message);
    
    /**
     * Create invalid tag exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcInvalidTagException(String message, Throwable cause);
}

PlcTagNotFoundException

/**
 * Exception thrown when tag is not found in PLC
 */
public class PlcTagNotFoundException extends PlcException {
    /**
     * Create tag not found exception with message
     * @param message Error description
     */
    public PlcTagNotFoundException(String message);
}

PlcTagRangeException

/**
 * Exception thrown when tag range is invalid or out of bounds
 */
public class PlcTagRangeException extends PlcException {
    /**
     * Create tag range exception with message
     * @param message Error description
     */
    public PlcTagRangeException(String message);
}

Data Type Exceptions

PlcIncompatibleDatatypeException

/**
 * Exception thrown when data type conversion fails
 */
public class PlcIncompatibleDatatypeException extends PlcException {
    /**
     * Create incompatible datatype exception with message
     * @param message Error description
     */
    public PlcIncompatibleDatatypeException(String message);
    
    /**
     * Create incompatible datatype exception with message and cause
     * @param message Error description
     * @param cause Underlying cause
     */
    public PlcIncompatibleDatatypeException(String message, Throwable cause);
}

Usage Examples:

import org.apache.plc4x.java.DefaultPlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.messages.*;

// Connection exception handling
PlcDriverManager driverManager = new DefaultPlcDriverManager();
try {
    PlcConnection connection = driverManager.getConnection("invalid-protocol://192.168.1.100");
    connection.connect();
} catch (PlcUnsupportedProtocolException e) {
    System.err.println("Protocol not supported: " + e.getMessage());
} catch (PlcConnectionException e) {
    System.err.println("Connection failed: " + e.getMessage());
    // Log full stack trace for debugging
    e.printStackTrace();
}

// Comprehensive error handling for read operations
try (PlcConnection connection = driverManager.getConnection("modbus-tcp://192.168.1.100:502")) {
    connection.connect();
    
    PlcReadRequest readRequest = connection.readRequestBuilder()
        .addTagAddress("sensor1", "holding-register:1")
        .addTagAddress("invalid_tag", "invalid-address")
        .build();
    
    try {
        PlcReadResponse response = readRequest.execute().get();
        
        // Handle individual tag response codes
        for (String tagName : response.getTagNames()) {
            try {
                PlcResponseCode code = response.getResponseCode(tagName);
                switch (code) {
                    case OK:
                        int value = response.getInteger(tagName);
                        System.out.println(tagName + ": " + value);
                        break;
                    case NOT_FOUND:
                        System.err.println("Tag not found: " + tagName);
                        break;
                    case ACCESS_DENIED:
                        System.err.println("Access denied for tag: " + tagName);
                        break;
                    case INVALID_ADDRESS:
                        System.err.println("Invalid address for tag: " + tagName);
                        break;
                    case INVALID_DATATYPE:
                        System.err.println("Invalid data type for tag: " + tagName);
                        break;
                    default:
                        System.err.println("Error reading " + tagName + ": " + code);
                        break;
                }
            } catch (PlcIncompatibleDatatypeException e) {
                System.err.println("Data type conversion failed for " + tagName + ": " + e.getMessage());
            }
        }
        
    } catch (PlcTimeoutException e) {
        System.err.println("Read operation timed out: " + e.getMessage());
    } catch (PlcIoException e) {
        System.err.println("I/O error during read: " + e.getMessage());
    } catch (PlcProtocolException e) {
        System.err.println("Protocol error: " + e.getMessage());
    }
    
} catch (PlcConnectionException e) {
    System.err.println("Connection error: " + e.getMessage());
}

// Write operation error handling
try (PlcConnection connection = driverManager.getConnection("s7://192.168.1.200/0/1")) {
    connection.connect();
    
    PlcWriteRequest writeRequest = connection.writeRequestBuilder()
        .addTagAddress("setpoint", "DB1.DBD0:REAL", 25.5f)
        .addTagAddress("readonly", "DB1.DBD4:REAL", 30.0f) // Might be read-only
        .build();
    
    try {
        PlcWriteResponse response = writeRequest.execute().get();
        
        for (String tagName : response.getTagNames()) {
            PlcResponseCode code = response.getResponseCode(tagName);
            switch (code) {
                case OK:
                    System.out.println("Successfully wrote " + tagName);
                    break;
                case ACCESS_DENIED:
                    System.err.println("Write access denied for " + tagName + " (tag might be read-only)");
                    break;
                case INVALID_DATA:
                    System.err.println("Invalid data value for " + tagName);
                    break;
                case INVALID_DATATYPE:
                    System.err.println("Data type mismatch for " + tagName);
                    break;
                default:
                    System.err.println("Write failed for " + tagName + ": " + code);
                    break;
            }
        }
        
    } catch (PlcProtocolPayloadTooBigException e) {
        System.err.println("Write payload too large: " + e.getMessage());
    } catch (PlcProtocolTimeoutException e) {
        System.err.println("Protocol timeout during write: " + e.getMessage());
    }
    
} catch (PlcUnsupportedOperationException e) {
    System.err.println("Write operations not supported by this driver: " + e.getMessage());
}

// Subscription error handling
try (PlcConnection connection = driverManager.getConnection("modbus-tcp://192.168.1.100:502")) {
    connection.connect();
    
    // Check capabilities first
    if (!connection.getMetadata().isSubscribeSupported()) {
        throw new PlcUnsupportedOperationException("Subscriptions not supported");
    }
    
    Consumer<PlcSubscriptionEvent> eventConsumer = event -> {
        try {
            for (String tagName : event.getTagNames()) {
                if (event.getResponseCode(tagName) == PlcResponseCode.OK) {
                    int value = event.getInteger(tagName);
                    System.out.println("Event - " + tagName + ": " + value);
                }
            }
        } catch (PlcIncompatibleDatatypeException e) {
            System.err.println("Data conversion error in event: " + e.getMessage());
        }
    };
    
    try {
        PlcSubscriptionRequest subscriptionRequest = connection.subscriptionRequestBuilder()
            .addCyclicTagAddress("sensor", "holding-register:1", Duration.ofSeconds(1))
            .setConsumer(eventConsumer)
            .build();
        
        PlcSubscriptionResponse response = subscriptionRequest.execute().get();
        
        if (response.getResponseCode("sensor") != PlcResponseCode.OK) {
            System.err.println("Subscription failed: " + response.getResponseCode("sensor"));
        }
        
        Thread.sleep(10000); // Monitor for 10 seconds
        
    } catch (PlcNotImplementedException e) {
        System.err.println("Cyclic subscriptions not implemented: " + e.getMessage());
    } catch (PlcUnsupportedDataTypeException e) {
        System.err.println("Data type not supported for subscription: " + e.getMessage());
    }
    
} catch (PlcUnsupportedOperationException e) {
    System.err.println("Subscriptions not supported: " + e.getMessage());
}

// Tag parsing error handling
try (PlcConnection connection = driverManager.getConnection("s7://192.168.1.200/0/1")) {
    connection.connect();
    
    try {
        // Try to parse a tag address
        Optional<PlcTag> tag = connection.parseTagAddress("DB1.INVALID_SYNTAX");
        if (tag.isPresent()) {
            System.out.println("Tag parsed successfully");
        } else {
            System.err.println("Tag parsing returned empty result");
        }
    } catch (PlcInvalidTagException e) {
        System.err.println("Invalid tag syntax: " + e.getMessage());
    }
    
    // Try to parse tag values
    try {
        PlcTag validTag = connection.parseTagAddress("DB1.DBD0:REAL").orElseThrow();
        Optional<PlcValue> value = connection.parseTagValue(validTag, "invalid_float_value");
        if (!value.isPresent()) {
            System.err.println("Value parsing failed");
        }
    } catch (PlcInvalidTagException e) {
        System.err.println("Tag validation failed: " + e.getMessage());
    } catch (PlcIncompatibleDatatypeException e) {
        System.err.println("Value type conversion failed: " + e.getMessage());
    }
}

// Utility method for centralized error handling
public static void handlePlcException(Exception e) {
    if (e instanceof PlcConnectionException) {
        System.err.println("Connection Error: " + e.getMessage());
        // Possibly retry connection
    } else if (e instanceof PlcTimeoutException) {
        System.err.println("Timeout Error: " + e.getMessage());
        // Possibly retry operation
    } else if (e instanceof PlcProtocolException) {
        System.err.println("Protocol Error: " + e.getMessage());
        // Log for debugging
    } else if (e instanceof PlcUnsupportedOperationException) {
        System.err.println("Operation not supported: " + e.getMessage());
        // Use alternative approach
    } else if (e instanceof PlcInvalidTagException) {
        System.err.println("Invalid tag: " + e.getMessage());
        // Validate tag addresses
    } else if (e instanceof PlcIncompatibleDatatypeException) {
        System.err.println("Data type error: " + e.getMessage());
        // Check data type compatibility
    } else if (e instanceof PlcException) {
        System.err.println("PLC Error: " + e.getMessage());
        // Generic PLC error handling
    } else {
        System.err.println("Unexpected error: " + e.getMessage());
        e.printStackTrace();
    }
}

Error Handling Best Practices

1. Check Capabilities First

PlcConnectionMetadata metadata = connection.getMetadata();
if (!metadata.isWriteSupported()) {
    throw new PlcUnsupportedOperationException("Write operations not supported");
}

2. Handle Response Codes

if (response.getResponseCode(tagName) == PlcResponseCode.OK) {
    // Process successful response
} else {
    // Handle specific error conditions
}

3. Use Try-With-Resources

try (PlcConnection connection = driverManager.getConnection(url)) {
    // Operations that may throw exceptions
} catch (PlcException e) {
    // Handle PLC-specific errors
}

4. Validate Inputs

Optional<PlcTag> tag = connection.parseTagAddress(tagAddress);
if (!tag.isPresent()) {
    throw new PlcInvalidTagException("Invalid tag address: " + tagAddress);
}

5. Log Detailed Information

catch (PlcException e) {
    logger.error("PLC operation failed", e);
    // Include context information in logs
}

The comprehensive exception hierarchy in Apache PLC4X provides fine-grained error handling capabilities, enabling robust industrial applications that can gracefully handle various failure scenarios common in industrial automation environments.

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-plc4x--plc4j-api

docs

browse-operations.md

connection-management.md

exception-handling.md

index.md

read-operations.md

subscription-system.md

value-system.md

write-operations.md

tile.json