docs: public void readExternal(final ObjectInput in) throws IOException,
                                                            ClassNotFoundException {
          // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to resolve the generated code references in Rules
          DroolsObjectInput droolsStream;
          boolean isDrools = in instanceof DroolsObjectInputStream;
  
          boolean wasDrools = in.readBoolean();
          if (wasDrools && !isDrools) {
              throw new IllegalArgumentException("The knowledge base was serialized using a DroolsObjectOutputStream. A DroolsObjectInputStream is required for deserialization.");
          }
  
          if (isDrools) {
              droolsStream = (DroolsObjectInput) in;
          } else {
              ByteArrayInputStream bytes = new ByteArrayInputStream((byte[]) in.readObject());
              droolsStream = new DroolsObjectInputStream(bytes);
          }
  
          boolean classLoaderCacheEnabled = droolsStream.readBoolean();
          Map<String, byte[]> store = (Map<String, byte[]>) droolsStream.readObject();
  
          this.rootClassLoader = createProjectClassLoader(droolsStream.getParentClassLoader(), store);
  
          droolsStream.setClassLoader(this.rootClassLoader);
          droolsStream.setKnowledgeBase(this);
  
          this.classFieldAccessorCache = new ClassFieldAccessorCache(this.rootClassLoader);
  
          this.config = (RuleBaseConfiguration) droolsStream.readObject();
          this.config.setClassLoader(droolsStream.getParentClassLoader());
  
          this.sessionConfiguration = new SessionConfigurationImpl( null, config.getClassLoader(), config.getChainedProperties() );
  
          kieComponentFactory = getConfiguration().getComponentFactory();
  
          this.pkgs = (Map<String, InternalKnowledgePackage>) droolsStream.readObject();
  
          for (InternalKnowledgePackage pkg : this.pkgs.values()) {
              pkg.getDialectRuntimeRegistry().onAdd(this.rootClassLoader);
          }
  
          // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to resolve the generated code references in Rules
          this.id = (String) droolsStream.readObject();
          this.workingMemoryCounter.set(droolsStream.readInt());
  
          this.processes = (Map<String, Process>) droolsStream.readObject();
          final String classNameFromStream = droolsStream.readUTF();
          try {
              Class cls = droolsStream.getParentClassLoader().loadClass(classNameFromStream);
              this.factHandleFactory = (FactHandleFactory) cls.newInstance();
          } catch (InstantiationException | IllegalAccessException e) {
              DroolsObjectInputStream.newInvalidClassException(classNameFromStream, e);
          }
  
          for (InternalKnowledgePackage pkg : this.pkgs.values()) {
              pkg.getDialectRuntimeRegistry().onBeforeExecute();
              pkg.getClassFieldAccessorStore().setClassFieldAccessorCache(this.classFieldAccessorCache);
              pkg.getClassFieldAccessorStore().wire();
          }
  
          this.populateTypeDeclarationMaps();
  
          // read globals
          Map<String, String> globs = (Map<String, String>) droolsStream.readObject();
          populateGlobalsMap(globs);
  
          this.eventSupport = (KieBaseEventSupport) droolsStream.readObject();
          this.eventSupport.setKnowledgeBase(this);
  
          this.reteooBuilder = (ReteooBuilder) droolsStream.readObject();
          this.reteooBuilder.setRuleBase(this);
          this.rete = (Rete) droolsStream.readObject();
  
          this.resolvedReleaseId = (ReleaseId) droolsStream.readObject();
  
          ( (DroolsObjectInputStream) droolsStream ).bindAllExtractors(this);
  
          if (!isDrools) {
              droolsStream.close();
          }
  
          this.getConfiguration().getComponentFactory().getTraitFactory().setRuleBase(this);
  
          rewireReteAfterDeserialization();
      }