|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +LabKey Server is a large Java web application platform for biomedical research data management. It uses a modular monolith architecture with 150+ Gradle modules, built on Spring Boot 4 / Spring Framework 7 with embedded Tomcat 11. It targets Java 25 and supports both PostgreSQL and MS SQL Server databases. |
| 8 | + |
| 9 | +## Build Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +# Configure IntelliJ IDEA project files |
| 13 | +./gradlew ijConfigure |
| 14 | + |
| 15 | +# Select database (populates application.properties from templates) |
| 16 | +./gradlew pickPg # PostgreSQL |
| 17 | +./gradlew pickMssql # MS SQL Server |
| 18 | + |
| 19 | +# Build and deploy to embedded Tomcat |
| 20 | +./gradlew deployApp |
| 21 | + |
| 22 | +# Build a specific module |
| 23 | +./gradlew :server:modules:platform:core:build |
| 24 | + |
| 25 | +# Build with a predefined module set |
| 26 | +./gradlew -PmoduleSet=community build |
| 27 | + |
| 28 | +# Exclude test modules for faster builds |
| 29 | +./gradlew -PexcludeTestModules build |
| 30 | + |
| 31 | +# Build a distribution |
| 32 | +./gradlew -PmoduleSet=distributions :distributions:base:dist |
| 33 | +``` |
| 34 | + |
| 35 | +## Running Tests |
| 36 | + |
| 37 | +**Unit tests** are static `TestCase` inner classes within production source files. They are registered via the module's `getUnitTests()` method and run within the server JVM. |
| 38 | + |
| 39 | +**Integration tests** require a running server and database. They are registered via `getIntegrationTests()`. |
| 40 | + |
| 41 | +**Selenium UI tests** (in `server/testAutomation/`): |
| 42 | +```bash |
| 43 | +./gradlew :server:testAutomation:initProperties # Generate test.properties |
| 44 | +./gradlew :server:testAutomation:uiTests -Psuite=DRT # Run a test suite |
| 45 | +``` |
| 46 | +UI tests require a running LabKey server, a browser driver (ChromeDriver or Geckodriver) on PATH, and configured `test.properties`. |
| 47 | + |
| 48 | +## Architecture |
| 49 | + |
| 50 | +### Module System |
| 51 | + |
| 52 | +Each module lives under `server/modules/` and contains: |
| 53 | +- `module.properties` — metadata including `ModuleClass`, `SchemaVersion`, `SupportedDatabases` |
| 54 | +- `build.gradle` — uses `org.labkey.build.module` plugin |
| 55 | +- A module class extending `SpringModule` (which extends `DefaultModule` implementing `Module`) |
| 56 | + |
| 57 | +Module lifecycle methods in order: `init()` → `versionUpdate()` → `afterUpdate()` → `startup()` → `startupAfterSpringConfig()` → `startBackgroundThreads()` → `destroy()` |
| 58 | + |
| 59 | +In `init()`, modules register controllers via `addController("name", Controller.class)` and set up service implementations. Controllers follow the pattern `*Controller.java`. |
| 60 | + |
| 61 | +### Core Platform Modules (`server/modules/platform/`) |
| 62 | + |
| 63 | +The `api` module provides the core framework (Module interface, SpringModule base class, services, utilities). Other key platform modules: `core` (auth, security, admin), `query` (SQL engine), `experiment`, `study`, `assay`, `pipeline` (job processing), `search`, `audit`, `visualization`. |
| 64 | + |
| 65 | +### Entry Point |
| 66 | + |
| 67 | +`server/embedded/src/org/labkey/embedded/LabKeyServer.java` — a `@SpringBootApplication` that configures embedded Tomcat, SSL/TLS, Content Security Policy, and Log4J2. |
| 68 | + |
| 69 | +### Database |
| 70 | + |
| 71 | +Dual database support (PostgreSQL and MS SQL Server). Configuration lives in `server/configs/application.properties`, populated by `pickPg`/`pickMssql` tasks from `pg.properties`/`mssql.properties` templates. Each module declares its `SchemaVersion` in `module.properties` and manages its own schema migrations. |
| 72 | + |
| 73 | +### Frontend |
| 74 | + |
| 75 | +Mix of JSPs, React (via `@labkey/components`), and ExtJS. Modules with JavaScript/TypeScript have their own `package.json` and use npm builds. Node.js and npm versions are pinned in `gradle.properties` and downloaded during build. |
| 76 | + |
| 77 | +### Distributions |
| 78 | + |
| 79 | +The `distributions/` directory defines 60+ distribution configurations that select which modules to package. Distributions inherit from each other (most inherit from `:distributions:base`). Distribution directory names must not collide with module names. |
| 80 | + |
| 81 | +### Dependency Management |
| 82 | + |
| 83 | +All external library versions are centralized in `gradle.properties` (200+ version properties). The root `build.gradle` forces consistent versions across all modules via `resolutionStrategy`. Always consult before adding, removing, or updating a third-party dependency. |
| 84 | + |
| 85 | +## Coding Conventions |
| 86 | + |
| 87 | +- **Java Streams**: Prefer `Stream` API over traditional for-loops for collection processing. |
| 88 | +- **Resources**: Use try-with-resources for automatic resource management. |
| 89 | +- **Nullability**: Use `org.jetbrains.annotations.NotNull` and `@Nullable`. Be explicit in public API signatures. |
| 90 | +- **Logging**: Use Log4J2. Name the static logger `LOG`, initialized via `LogHelper.getLogger()`: |
| 91 | + ```java |
| 92 | + private static final Logger LOG = LogHelper.getLogger(MyClass.class, "optional description"); |
| 93 | + ``` |
| 94 | +- **Unit tests**: Create a static `TestCase` inner class extending `Assert` in the same file as production code. Use JUnit 4 annotations (`@Test`). Register new test classes in the owning module's `getUnitTests()`. |
| 95 | +- **Selenium tests**: Subclass `BaseWebDriverTest`. Use a `@BeforeClass` for setup and override `doCleanup()` for cleanup. See `SecurityTest` as an example. |
| 96 | +- **Formatting**: Follow IntelliJ IDEA project settings in `.idea/codeStyles/Project.xml`. |
| 97 | + |
| 98 | +## Key Build Properties (`gradle.properties`) |
| 99 | + |
| 100 | +- `sourceCompatibility`/`targetCompatibility`: Java 25 |
| 101 | +- `buildFromSource`: true (build modules from source vs. pulling artifacts) |
| 102 | +- `useLocalBuild`: use locally built artifacts |
| 103 | +- `moduleSet`: select a predefined set of modules (e.g., `community`, `all`, `distributions`) |
| 104 | +- `excludedModules`: comma-separated list of modules to exclude |
| 105 | + |
| 106 | +## Search Tips |
| 107 | + |
| 108 | +When searching for Java method usages, always include `*.jsp` and `*.jspf` files in addition to `*.java`. JSP files contain inline Java code and are significant callers of API methods (especially anything in `JspBase`). |
| 109 | + |
| 110 | +## Pull Request Format |
| 111 | + |
| 112 | +PRs should include sections for: **Rationale** (why the change is needed), **Related Pull Requests**, and **Changes** (notable items). |
0 commit comments