How do you declare a custom Maven repository and an Ivy repository in Gradle, and when would you reach for `flatDir`?
answer
- maven { url = uri(...) }
- ivy { patternLayout {...} }
- flatDir = no metadata, last resort
- name maps credentials
- file:// keeps metadata, unlike flatDir
basics
~20 sUse maven { url = uri("https://...") } for a Maven-layout server and ivy { url = uri("...") } (often with a patternLayout) for an Ivy-layout server. flatDir { dirs("libs") } points at a folder of bare JARs with no metadata — a last resort.
solid answer
~50 sFor a custom Maven-layout server you declare `maven { url = uri("https://repo.example.com") }`. Gradle then expects the standard Maven path layout (`group/name/version/...`) and `.pom`/`.module` metadata. For a server using **Ivy** layout you use `ivy { url = uri("...") }`, and when its paths differ from the default you supply a `patternLayout { artifact("..."); ivy("...") }` so Gradle knows how to build the URLs. `flatDir { dirs("libs") }` registers a plain directory of JARs that carry **no metadata at all** — so Gradle cannot determine their transitive dependencies and you must declare those yourself. `flatDir` is a last resort for legacy/vendored JARs you can't get from a real repo; the better fix is to publish them to a proper Maven/Ivy repository. You can also point `maven`/`ivy` at a `file://` URL for a local directory laid out in repository format, which keeps metadata intact unlike `flatDir`.
code
kotlin · 10 linesrepositories {
maven { url = uri("https://repo.example.com/releases") }
ivy {
url = uri("https://ivy.example.com")
patternLayout {
artifact("[organisation]/[module]/[revision]/[artifact]-[revision].[ext]")
}
}
flatDir { dirs("libs") } // metadata-less; declare transitives yourself
}go deeper
Know maven { url = uri(...) } adds a custom repo.
Differentiate maven/ivy/flatDir and that flatDir lacks metadata; mention patternLayout for Ivy.
Recommend publishing vendored JARs to a real repo over flatDir; use file:// to preserve metadata.
Standardize on a curated internal Maven repo; forbid flatDir in shared builds for reproducibility and transitive-correctness reasons.
## Custom Maven repository Most third-party and internal repos use Maven layout. Declare them with the `maven {}` repository and a URL: ```kotlin repositories { maven { url = uri("https://repo.spring.io/release") } maven { name = "corpNexus" url = uri("https://nexus.corp/repository/maven-releases/") } } ``` Gradle assumes the standard Maven path layout and looks for `.pom` (and `.module`, if present) metadata. The optional `name` is used for tasks and, importantly, to map credentials from `gradle.properties` (`corpNexusUsername` / `corpNexusPassword`). ## Ivy repository Ivy was Ant's dependency manager; some legacy infrastructure still serves Ivy-layout repos. Declare with `ivy {}`: ```kotlin repositories { ivy { url = uri("https://ivy.corp/repo") patternLayout { artifact("[organisation]/[module]/[revision]/[artifact]-[revision].[ext]") ivy("[organisation]/[module]/[revision]/ivy-[revision].xml") } } } ``` The `patternLayout` tells Gradle how to construct artifact and metadata URLs from the coordinates — necessary because Ivy repos don't follow Maven's fixed convention. There's also `m2compatible` and `metadataSources {}` to control what metadata Gradle trusts. ## flatDir — the metadata-less last resort ```kotlin repositories { flatDir { dirs("libs", "vendor/jars") } } dependencies { implementation(":legacy-sdk:1.0") // group may be empty } ``` `flatDir` exposes a directory of bare JARs. Because there is **no metadata**, Gradle cannot resolve transitive dependencies — you must declare every transitive dependency of those JARs by hand, and you lose variant-aware resolution. Use it only for vendored/legacy artifacts you genuinely cannot host elsewhere; the recommended fix is to publish them into a real Maven/Ivy repository (even a `file://` one) so metadata is preserved. ## file:// repositories Both `maven` and `ivy` accept a `file://` URL pointing at a directory laid out in repository format. Unlike `flatDir`, this keeps full metadata, so it's the preferred way to consume a locally-built repository. ## When to use which - `maven {}` — almost always, for any Maven-layout HTTP(S) or `file://` source. - `ivy {}` — only when the server genuinely uses Ivy layout. - `flatDir {}` — last resort, metadata-less, declare transitives manually.
- Why is flatDir considered a last resort?It exposes JARs with no metadata, so Gradle can't resolve their transitive dependencies or variants — you must declare every transitive dependency manually. A real Maven/Ivy repo (even file://) preserves metadata.
- What does patternLayout do in an ivy {} repository?It defines URL patterns Gradle uses to locate artifacts and Ivy metadata from coordinates, since Ivy repos don't follow Maven's fixed layout.
- How can a custom maven repo's name interact with credentials?Setting `name = "corpNexus"` lets Gradle pick up `corpNexusUsername`/`corpNexusPassword` from gradle.properties for that repo.
saying these in an interview costs you the question
- Treating flatDir as equivalent to a Maven repo (it has no metadata).
- Using a raw string instead of uri(...) where a URI is required and getting confused by deprecation.
- Reaching for ivy {} when the server is actually Maven-layout.