Class McpDateModule

java.lang.Object
tools.jackson.databind.JacksonModule
tools.jackson.databind.module.SimpleModule
com.mcpdbwizard.pub.McpDateModule
All Implemented Interfaces:
Serializable, tools.jackson.core.Versioned

public final class McpDateModule extends tools.jackson.databind.module.SimpleModule
McpDates as a Jackson module, so a date crosses the same way inside a RECORD as it does as a parameter of its own.

What this fixes

The generated server binds a PL/SQL record parameter through Jackson, and configured it with .defaultDateFormat(new SimpleDateFormat(McpDates.ISO_PATTERN)). Handing Jackson the PATTERN gets none of the parsing McpDates wraps around it, and a SimpleDateFormat on that pattern has two habits that are exactly the defects McpDates exists to prevent: parse(String) stops at the end of the pattern and IGNORES what follows, and it is LENIENT. Measured, before this module, against the mapper the emitter actually builds:

   input                        in a record          as a scalar parameter
   1980-01-01                   REFUSED              1980-01-01 00:00:00
   1980-01-01T09:30             REFUSED              1980-01-01 09:30:00
   1980-01-01T09:30:00+05:30    09:30:00 +0000       04:00:00 +0000    offset DROPPED
   1980-01-01T09:30:00.500      09:30:00.000         09:30:00.500      fraction DROPPED
   2003-13-45T00:00:00          2004-02-14           REFUSED           rolled, silently
 

Only the first of those five is visible. The bare date fails closed, which is why it is the one that got reported; the three below it produce a plausible wrong answer and tell nobody. A departure time sent as +05:30 was stored five and a half hours out.

Outbound had the same shape of loss: a Timestamp FIELD rendered through the DATE pattern and dropped its fractional seconds, because Timestamp extends Date and only McpDates.formatAny(java.util.Date) dispatches on that.

Why a module rather than a format

A DateFormat can only describe one spelling. The accepted set is a date, optionally a time, optionally an offset — which is a parser, not a pattern, and McpDates already is that parser. Registering it here means the two paths cannot drift, because there is only one.

Why this is a separate class from McpDates

So that McpDates stays free of Jackson types. It is reached by every generated DAO, including those in applications that never touch MCP and have no Jackson on the classpath; this class is loaded only by a generated MCP server, which always does.

Since:
2.0.17
Version:
1
Author:
[email protected] Copyright 2003-2026 ATB Consultancy Services Ltd (formerly Orinda Software Ltd, Dublin, Ireland)
See Also:
  • Nested Class Summary

    Nested classes/interfaces inherited from class tools.jackson.databind.JacksonModule

    tools.jackson.databind.JacksonModule.SetupContext
  • Field Summary

    Fields inherited from class tools.jackson.databind.module.SimpleModule

    _abstractTypes, _defaultNullKeySerializer, _defaultNullValueSerializer, _deserializerModifier, _deserializers, _id, _keyDeserializers, _keySerializers, _mixins, _name, _namingStrategy, _serializerModifier, _serializers, _subtypes, _valueInstantiators, _version
  • Constructor Summary

    Constructors
    Constructor
    Description
    Register McpDates for both date types a generated class can declare.
  • Method Summary

    Methods inherited from class tools.jackson.databind.module.SimpleModule

    _checkNotNull, addAbstractTypeMapping, addDeserializer, addKeyDeserializer, addKeySerializer, addSerializer, addSerializer, addValueInstantiator, getModuleName, getRegistrationId, registerSubtypes, registerSubtypes, registerSubtypes, setAbstractTypes, setDefaultNullKeySerializer, setDefaultNullValueSerializer, setDeserializerModifier, setDeserializers, setKeyDeserializers, setKeySerializers, setMixInAnnotation, setNamingStrategy, setSerializerModifier, setSerializers, setupModule, setValueInstantiators, version

    Methods inherited from class tools.jackson.databind.JacksonModule

    getDependencies

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • McpDateModule

      public McpDateModule()
      Register McpDates for both date types a generated class can declare.

      Those two are the whole surface. The generator maps an Oracle date column or attribute to java.util.Date or java.sql.Timestamp and to nothing else — there is no java.sql.Date and no java.time field to cover. Registering a type that cannot occur would be dead code that looks like caution.

      Jackson matches a deserializer on the DECLARED field type, so Timestamp needs its own entry even though it extends Date: without one it would fall back to Jackson's default and lose the fractional seconds that are the only reason the type differs.