Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8299571

ZoneRulesProvider.registerProvider() can leave inconsistent state on failure

    XMLWordPrintable

Details

    • b05
    • generic
    • generic
    • Verified

    Description

      ADDITIONAL SYSTEM INFORMATION :
      openjdk version "21-ea" 2023-09-19
      OpenJDK Runtime Environment (build 21-ea+3-124)
      OpenJDK 64-Bit Server VM (build 21-ea+3-124, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      When registering a `java.time.zone.ZoneRulesProvider` via the `registerProvider()` method the call can fail when a zone id is already registered with another provider. The zone ids of the provider are registered one by one until the first failure. The thrown `ZoneRulesException` then prevents subsequent update code of `ZONE_IDS` and `PROVIDERS` to run and update the caches leaving the whole class in an inconsistent state where some new zone ids are registered but not given out with `getAvailableZoneIds()`.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Register a ZoneRulesProvider with new zone id and already registered zone id.
      It will fail with an exception but the new zone id will nevertheless be registered with the provider but not appear in aviabale zone ids.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Either the registering needs to fail completely, then neither of `ZONE_IDS`, `PROVIDERS` nor `ZONES` are allowed to change and also none of the ZoneIds are then available XOR the registering can fail for single zone ids but non-present are registered and all caches are updated properly
      ACTUAL -
      New zone ids are registered but caches are not updated.

      ---------- BEGIN SOURCE ----------
      import java.time.zone.*;
      import java.time.*;
      import java.util.*;
      public class ZoneRulesProviderTest {
        static abstract class CustomZoneRulesProvider extends ZoneRulesProvider {
          public ZoneRules provideRules(String zoneId, boolean forCaching){ return null; }
          public NavigableMap<String, ZoneRules> provideVersions(String zoneId) { return new TreeMap<>(); }
        }
        
        public static void main(String... args) {
          
        Set<String> zoneIds = new LinkedHashSet<>();
        zoneIds.add("MyZoneId"); zoneIds.add("CET");
        try {
          ZoneRulesProvider.registerProvider(new CustomZoneRulesProvider() {
            public Set<String> provideZoneIds() { return zoneIds; }
          });
        } catch(ZoneRulesException e) { e.printStackTrace(); } // Unable to register zone as one already registered with that ID: CET
        ZoneId.getAvailableZoneIds().contains("MyZoneId"); // false
        ZoneId.of("MyZoneId"); // returns a ZoneId, no exception
        
        // now registering another Provider will update the ZONE_IDS cache
        ZoneRulesProvider.registerProvider(new CustomZoneRulesProvider() {
          public Set<String> provideZoneIds() { return Set.of("AnotherZoneId"); }
        });
        ZoneId.getAvailableZoneIds().contains("MyZoneId"); // true
        ZoneId.getAvailableZoneIds().contains("AnotherZoneId"); // true
        
        ZoneRulesProvider.refresh(); // will not call the first Provider as it is not stored in PROVIDERS
      }}
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Register another ZoneRulesProvider to force at least an update of the cached `ZONE_IDS`.

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              naoto Naoto Sato
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: