# Spring Property and Value Resolution Strategy ## 1. The Challenge of "Injected" Metadata In Spring, metadata (like Queue names, Topic names, or even Event names) is often not hardcoded but injected using various mechanisms. To provide an accurate map, the analyzer must resolve these values. ## 2. Supported Injection Patterns ### Field Injection ```java @Value("${app.order-queue}") private String orderQueue; ``` **Static Strategy**: 1. Scan all fields for `@Value`. 2. Map `FieldName` -> `Placeholder/Value`. 3. If `${...}` is found, resolve it via the `PropertyResolver`. ### Constructor and Setter Injection ```java public OrderService(@Value("${app.event.submit}") String submitEvent) { this.submitEvent = submitEvent; } ``` **Static Strategy**: 1. Scan constructor/method parameters for `@Value`. 2. Trace the assignment to a class field (`this.submitEvent = ...`). 3. Store the mapping for that field. ### @ConfigurationProperties ```java @ConfigurationProperties(prefix = "app.messaging") public class AppProps { private String queueName; } ``` **Static Strategy**: 1. Identify `@ConfigurationProperties` classes. 2. Index their fields with the prefix (e.g., `app.messaging.queueName`). 3. When these beans are injected into a service, link the service's usage to the resolved property value. ## 3. Profile-Aware Property Resolver A component dedicated to building a multi-dimensional map of available properties. 1. **File Scanning**: Parse `application.properties`, `application.yml`, and `bootstrap.yml`. 2. **Profile Identification**: - From filenames: `application-{profile}.properties`. - From YAML documents: `spring.config.activate.on-profile` (Spring Boot 2.4+). 3. **The Multi-Profile Map**: - Instead of one map, we store: `Map>`. - The "default" profile is the base. ## 4. Smart Value Propagation When a trigger uses a property, we want to know it's profile-dependent. **Example Trace**: 1. `application.yml` -> `app.queue: "orders"` 2. `application-prod.yml` -> `app.queue: "orders-prod"` 3. `TriggerPoint` stores: - `placeholder: "${app.queue}"` - `defaultResolvedValue: "orders"` 4. **Rendering Strategy**: The renderer can show "orders" by default, but provide a "Profile Toggle" to switch to "prod" and see the labels update to "orders-prod". ## 5. Metadata Retention We should never "squash" profiles during analysis. The `CodebaseMetadata` will carry the full profile matrix to the exporter. ## 5. SpEL (Spring Expression Language) Lite Full SpEL support is hard for static analysis, but we can support "Common Patterns": - Simple bean property access: `#{myBean.name}` - System properties: `#{systemProperties['user.dir']}` - Ternary operators: `${app.enabled ? 'active' : 'inactive'}` ## 6. Constant Resolution If an annotation uses a reference to a constant: ```java @RabbitListener(queues = MyConstants.ORDER_QUEUE) ``` **Static Strategy**: 1. Use JDT to resolve the `QualifiedName` (`MyConstants.ORDER_QUEUE`). 2. Fetch the `TypeDeclaration` for `MyConstants`. 3. Find the `VariableDeclarationFragment` for `ORDER_QUEUE` and extract its literal initializer.