Integration with external LIMS fails on unit conversion for ingredient quantities in recipe management

We’re syncing ingredient data from an external LIMS system to ENOVIA R2021x recipe management via REST API. The integration fails when ingredient quantities use different unit systems between LIMS and ENOVIA.

Example REST payload from LIMS:

POST /resources/v1/formulation/Ingredient
{
  "name": "Sodium Chloride",
  "quantity": 250,
  "unit": "g"
}

ENOVIA expects units in “kg” for bulk ingredients. Error: “Unit mismatch: expected ‘kg’, received ‘g’”

The LIMS system uses metric units (g, mg, ml) while ENOVIA recipes are configured for production units (kg, L). Unit conversion logic needs to happen during the sync but we’re not sure where to implement it - in the middleware transformation layer or within ENOVIA’s REST service. The LIMS integration handles 2000+ ingredient records daily across 50+ formulations. Need an efficient approach that doesn’t break either system’s unit conventions.

Here’s a comprehensive solution addressing all three focus areas:

1. Unit Conversion Logic - Architectural Approach

Implement a three-layer unit conversion strategy:

Layer 1: Middleware Transformation (Primary)

Create a dedicated unit conversion service in MuleSoft:

// Pseudocode - Unit conversion service:
1. Load conversion rules from configuration database
2. Identify source unit and target unit from mapping table
3. Retrieve ingredient-specific conversion factors if applicable
4. Apply conversion using BigDecimal arithmetic
5. Validate result against acceptable ranges
6. Return converted value with precision metadata
// Configuration: ingredient_class -> target_unit mappings

Conversion rules configuration:

{
  "conversionRules": [
    {
      "sourceUnit": "g",
      "targetUnit": "kg",
      "factor": "0.001",
      "precision": 6
    },
    {
      "sourceUnit": "mg",
      "targetUnit": "kg",
      "factor": "0.000001",
      "precision": 9
    }
  ]
}

Layer 2: ENOVIA Validation (Safety Net)

Configure ENOVIA recipe management to accept multiple units and convert internally:

// ENOVIA custom service
public class IngredientImportService {

  public void importIngredient(IngredientData data) {
    String targetUnit = getPreferredUnit(
      data.getIngredientClass());

    if (!data.getUnit().equals(targetUnit)) {
      data = convertUnit(data, targetUnit);
      logConversion(data, "Middleware conversion missed");
    }

    validateQuantity(data);
    persistIngredient(data);
  }
}

Layer 3: Validation and Reconciliation

Implement post-import validation:

-- Daily reconciliation query
SELECT ingredient_id, quantity, unit
FROM enovia_ingredients
WHERE unit NOT IN (SELECT preferred_unit
                   FROM ingredient_classes)
OR quantity > max_expected_quantity
OR quantity < min_expected_quantity;

2. Middleware Transformation - Implementation Details

MuleSoft flow for LIMS to ENOVIA integration:

<!-- Pseudocode - MuleSoft flow structure:
1. Receive LIMS ingredient data (REST/SOAP/File)
2. Enrich with ingredient class from ENOVIA lookup
3. Call unit conversion service with:
   - Current quantity and unit
   - Target unit from ENOVIA preferences
   - Ingredient-specific factors (if applicable)
4. Transform payload to ENOVIA REST format
5. Validate converted data against business rules
6. POST to ENOVIA REST API with retry logic
7. Log conversion details for audit trail
-->

Conversion service implementation:

public class UnitConversionService {

  public ConversionResult convert(
    BigDecimal quantity,
    String sourceUnit,
    String targetUnit,
    String ingredientClass) {

    // Get conversion factor
    ConversionRule rule = ruleRepository
      .findByUnits(sourceUnit, targetUnit);

    // Apply ingredient-specific adjustments
    BigDecimal factor = rule.getFactor();
    if (requiresDensityAdjustment(ingredientClass)) {
      factor = adjustForDensity(factor, ingredientClass);
    }

    // Convert with specified precision
    BigDecimal converted = quantity
      .multiply(factor)
      .setScale(rule.getPrecision(),
                RoundingMode.HALF_UP);

    // Validate result
    validateRange(converted, ingredientClass);

    return new ConversionResult(
      converted,
      targetUnit,
      rule.getPrecision()
    );
  }
}

3. LIMS Integration - Complete Solution

Configuration Management:

Create a unit mapping configuration accessible to both systems:

{
  "ingredientClasses": [
    {
      "class": "BULK_SOLID",
      "limsUnit": "g",
      "enoviaUnit": "kg",
      "conversionFactor": "0.001",
      "precision": 3,
      "minQuantity": 0.001,
      "maxQuantity": 10000
    },
    {
      "class": "ACTIVE_INGREDIENT",
      "limsUnit": "mg",
      "enoviaUnit": "kg",
      "conversionFactor": "0.000001",
      "precision": 9,
      "minQuantity": 0.000001,
      "maxQuantity": 1.0
    }
  ]
}

Error Handling:

public class ConversionErrorHandler {

  public void handleConversionError(
    IngredientData data,
    ConversionException ex) {

    // Log detailed error
    logger.error("Conversion failed: {} {} to {}",
      data.getQuantity(),
      data.getUnit(),
      data.getTargetUnit(),
      ex);

    // Queue for manual review
    reviewQueue.add(data);

    // Notify formulation team
    notificationService.alert(
      "Unit conversion failed for " +
      data.getIngredientName());
  }
}

Performance Optimization for 2000+ Daily Records:

  1. Batch Processing: Group LIMS records into batches of 100 for conversion and import
  2. Caching: Cache conversion rules and ingredient class mappings (refresh hourly)
  3. Parallel Processing: Use MuleSoft’s parallel processing for independent conversions
  4. Async Import: Queue converted records for asynchronous ENOVIA import

Implementation Roadmap:

Week 1: Middleware Setup

  • Create unit conversion service in MuleSoft
  • Configure conversion rules database
  • Implement BigDecimal-based conversion logic
  • Add validation and error handling

Week 2: ENOVIA Configuration

  • Configure preferred units per ingredient class
  • Implement ENOVIA-side conversion safety net
  • Set up validation rules and acceptable ranges
  • Create monitoring dashboard

Week 3: Integration Testing

  • Test all unit combinations (g→kg, mg→kg, ml→L)
  • Validate precision preservation
  • Test edge cases (density adjustments, compound units)
  • Performance test with 2000+ record batches

Week 4: Production Rollout

  • Deploy middleware conversion service
  • Enable ENOVIA validation layer
  • Implement monitoring and alerting
  • Document conversion rules and maintenance procedures

This three-layer approach ensures robust unit conversion while maintaining system independence. The middleware handles primary conversion, ENOVIA provides validation safety, and comprehensive error handling catches edge cases before they corrupt recipe data.


This draft is based on general ENOVIA knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

Unit conversion should definitely happen in the middleware layer, not in ENOVIA. Your LIMS and ENOVIA systems should each maintain their native unit conventions. The integration layer transforms data between systems. Build a unit conversion service that maps LIMS units to ENOVIA units before posting to the REST API.

That makes sense. We’re using MuleSoft as middleware. Should we create a dedicated unit conversion component or embed the conversion logic directly in the LIMS-to-ENOVIA flow? Also concerned about precision loss when converting between units - formulation recipes need exact quantities.

Create a reusable unit conversion service in MuleSoft that can be called by any integration flow. Use a configuration-driven approach with a conversion rules database. For precision, use BigDecimal arithmetic and define precision requirements per ingredient type. Critical ingredients might need 6 decimal places while bulk ingredients need only 2. Store conversion factors as exact ratios rather than floating point decimals to avoid rounding errors.

Consider implementing the conversion logic on the ENOVIA side as well, not just middleware. ENOVIA R2021x recipe management supports unit conversion rules that can be configured per ingredient class. This provides a safety net - if middleware sends incorrect units, ENOVIA can still convert them. It also allows manual recipe entry with flexible units while maintaining production-standard units internally. Configure ENOVIA’s preferred units and enable automatic conversion on import.

Watch out for edge cases in unit conversion: temperature-dependent density for volume-to-weight conversions, ingredient-specific gravity variations, and compound units like concentration (mg/L). Your conversion logic needs to handle these complexities or flag them for manual review. Also implement validation - compare converted values against expected ranges to catch conversion errors before they corrupt recipe data.

Excellent points about edge cases and validation. We definitely need robust conversion logic with error handling. The dual-layer approach (middleware + ENOVIA) sounds like good defensive design.