Skip to main content
Back to AutoCore Hub

Bridge Node Analysis

A bridge node in a knowledge graph is a class that, if removed, would sever the connection between two otherwise-isolated communities. They are dangerous because they accumulate hidden responsibilities that cross architectural boundaries.


Bridge 1: HawkSearchDataFeedServices

Package: com.hotwax.hawksearch
File: HawkSearchDataFeedServices.java (2,861 lines)
Communities bridged: HawkSearch (export pipeline) ↔ AutoCore Solr (indexing infrastructure)

Bridge 1: HawkSearch → AutoCore Solr via IndexingServicesUse mouse wheel to zoom, drag to pan • Pull bottom edge to resize

Why It's a Bridge — The Exact Code Path

The bridge is a single static method call:

// hawkFeedUsingSolr()
try (HttpSolrClient server = new HttpSolrClient.Builder(
IndexingServices.getSolrHost(delegator, "globalproducts")).build();
HttpSolrClient memberServer = new HttpSolrClient.Builder(
IndexingServices.getSolrHost(delegator, "memberproduct")).build()) {

IndexingServices lives in com.hotwax.autocore.autocoresolr.index — completely different package, completely different community. The only external dependency the HawkSearch module has on the AutoCore Solr community. Cut it and the two communities have zero edges between them.

What hawkFeedUsingSolr Actually Does

It is the "Solr-native" path for generating HawkSearch data feeds:

  1. Calls IndexingServices.getSolrHost() to resolve the globalproducts and memberproduct Solr URLs
  2. Opens a direct HttpSolrClient connection to both cores
  3. Runs filter queries against globalproducts (by brand, status, date delta, salesDiscontinuationDate)
  4. Feeds raw Solr documents through FreeMarker templates to generate items.txt and attributes.txt
  5. Queries memberproduct for distributor pricing and WD availability
  6. Writes distributor.txt based on the join between the two Solr cores

It's essentially Solr-as-database: bypasses OFBiz entities entirely and reads pre-indexed documents directly.

What Breaks If This Class Changes

ChangeDownstream Breakage
IndexingServices.getSolrHost() signature changeshawkFeedUsingSolr immediately fails to compile
Solr core renamed from globalproducts or memberproductSilent failure: HawkSearch feed generates 0 products
IndexingServices package refactoredAll import statements at top of file break
HawkSearch feed schedule changesDataFeedConfigGroup.lastFeedTimestamp is read from DB to filter delta query — change entity and partial feeds break
isHawkIndexed / hawkIndexedDate fields removed from Product entityprepareItemsDataFeed (RDBMS-path method) breaks completely

Most dangerous scenario: If IndexingServices is made package-private during a refactor, HawkSearch feed generation silently stops — no compile error, just a NoSuchMethodError at runtime.

Is It Intentional Design or Accidental Coupling?

Accidental coupling that became intentional over time.

hawkFeedUsingSolr was added later as a "faster" alternative to prepareItemsDataFeed and the developer reached across packages to reuse IndexingServices.getSolrHost() rather than duplicating the property-lookup logic.

The right design: A SolrConnectionFactory or SolrConfigService in a shared utilities package that both HawkSearch and ProductSolrServices consume.


Bridge 2: AutoCoreLoginWorker

Package: com.hotwax.autocore.login
File: AutoCoreLoginWorker.java (143 lines)
Communities bridged: Auth/Session (login, reports) ↔ Party/DataImport (the main AutoCore service graph)

Bridge 2: AutoCoreLoginWorker — Session as Implicit ContractUse mouse wheel to zoom, drag to pan • Pull bottom edge to resize

Why It's a Bridge — The Exact Code Path

AutoCoreLoginWorker is registered as a servlet pre-event in controller.xml, firing on every HTTP request. The method checkPartDomain performs live Party entity queries:

// checks if user is an AutoCore employee
EntityQuery.use(delegator).from("PartyRelationship")
.where("partyIdFrom", "AutoCore", "partyIdTo", loginPartyId,
"roleTypeIdFrom", "ASSOCIATION", "roleTypeIdTo", "EMPLOYEE")
.filterByDate().queryFirst();

The values it writes to the session — memberPartyId and partDomainId — are consumed by DataImportServices on 20+ call sites.

Why Session-As-Bus Is More Dangerous Than Direct Import

With HawkSearchDataFeedServices, the coupling is visible as a compile-time import — grep finds it. With AutoCoreLoginWorker, the coupling is:

  1. Invisible to static analysis — no import statement, no type reference
  2. Convention-based — renaming the string key "partdomain" in either class fails silently at compile time
  3. Pre-emptive — a bug here blocks the entire admin console, not just one service

What Breaks If This Class Changes

ChangeDownstream Breakage
checkPartDomain returns "error" instead of "success"Every admin UI request blocked. OFBiz routes to error page
Session key renamed from "partDomainId" to "domainPartyId"All import services silently fail — every store* call in DataImportServices returns error
Party hierarchy restructured (MEMBER → DOMAIN_PARTY relationship removed)checkPartDomain never resolves the partDomainId, users loop on SelectPartDomain redirect forever
AutoCoreLoginWorker removed from controller.xmlAll import UI flows have null partDomainId — all product create/delete operations fail
New role type added between EMPLOYEE and DOMAIN_PARTYUsers with new role are routed to SelectPartDomain indefinitely (no matching branch in the 3-case if-else)

Is It Intentional Design or Accidental Coupling?

Intentional design, but naively implemented.

The intent is correct: enforce multi-tenancy by scoping every admin session to a specific partDomain (the franchise territory). The problem is that the bridge is implicit — the contract between checkPartDomain (writer) and DataImportServices (reader) is just a string key in a HashMap. Not enforced by any interface, not documented in any service definition file.

The right design: partDomainId should be passed as an explicit service parameter defined in the service XML definition, with its source handled by a proper security service, not a pre-event filter that writes to untyped session state.


Summary Comparison

PropertyHawkSearchDataFeedServicesAutoCoreLoginWorker
Bridge mechanismCompile-time import (IndexingServices)Runtime convention (HTTP session key)
VisibilityHigh — grep for the importLow — invisible to static analysis
Failure modeHard compile error → caught earlySilent null at runtime → caught in production
Design intentAccidental (developer shortcut)Intentional (multi-tenancy enforcement)
Risk of changeMedium — isolated to HawkSearch feedsHigh — affects every admin import operation
FixExtract SolrConnectionFactory to shared utilDefine partDomainId as explicit service param in XML
Communities bridgedHawkSearch ↔ SolrAuth ↔ DataImport
Bridge Risk Matrix: Visibility vs Risk of ChangeUse mouse wheel to zoom, drag to pan • Pull bottom edge to resize