What does exported=false do at the repository, query-method, and association level, and what is the gotcha when you hide a repository that backs an association?
answer
- exported=false = hide from HTTP, keep the bean
- three scopes: repo / query method / association
- association resolved by target repo's URI
- hide target repo -> association link breaks
- ALL strategy ignores exported=false
basics
~20 sexported=false stops Spring Data REST from publishing something over HTTP while keeping it as a normal Spring bean. On a repository it hides all its endpoints; on a query method it hides that finder; on an association it drops the association resource. Gotcha: hiding a repository can break linking to its entities.
solid answer
~40 s`exported = false` tells Spring Data REST *not* to publish a resource, without removing the underlying Java artifact. On `@RepositoryRestResource` it removes the repository's entire HTTP surface (collection, item, search) but the repository bean is still injectable in your code. On `@RestResource` over a query method, that single finder disappears from `/search`. On `@RestResource` over an entity property/association, the association resource (e.g. `/orders/{id}/customer`) is not exposed. The classic gotcha: if you set `exported = false` on a repository whose entity is the *target* of an association from an exported entity, clients can no longer resolve or set that association by URI — because SDR needs an exported repository to build item URIs. So partially hiding entity graphs can produce non-functional or read-only associations.
code
java · 20 lines// 1) Whole repository hidden from REST, still an injectable bean
@RepositoryRestResource(exported = false)
public interface AuditRepository extends JpaRepository<AuditRow, Long> { }
// 2) Hide one finder from /search, keep it callable in Java
public interface OrderRepository extends JpaRepository<Order, Long> {
@RestResource(exported = false)
List<Order> findBySecretToken(String token);
}
// 3) Association gotcha: Order.customer becomes non-resolvable over REST
// because CustomerRepository below is not exported -> /customers/{id} URI
// does not exist for SDR to emit or accept.
@RepositoryRestResource(exported = false)
public interface CustomerRepository extends JpaRepository<Customer, Long> { }
@Entity class Order {
@Id @GeneratedValue Long id;
@ManyToOne Customer customer; // link cannot be set via /orders/{id}/customer
}go deeper
Know exported=false hides a repository's REST endpoints but keeps it usable in code.
Distinguish the three scopes and give a concrete use for each.
Explain the association-by-URI mechanism and why hiding a target repository breaks linking to it.
Design the exported surface as a deliberate contract; audit that opt-outs don't strand associations, and remember the ALL strategy overrides exported=false.
**Purpose of exported=false.** It is SDR's way to say 'this exists in code but must not appear on the HTTP API.' The Java artifact — repository bean, query method, entity field — remains fully usable internally; only its REST projection is suppressed. **Three scopes.** 1. **Repository level** — `@RepositoryRestResource(exported = false)` on the interface. All generated endpoints for that repository (collection `/foos`, items `/foos/{id}`, `/foos/search`) are removed. You'd still `@Autowired FooRepository` and use it from services or your own controllers. Use this to keep a repository purely internal. 2. **Query-method level** — `@RestResource(exported = false)` on a `findBy…` method. That finder is dropped from the `/search` listing and cannot be invoked over HTTP, but remains callable in Java. Useful for finders that expose sensitive predicates. 3. **Property/association level** — `@RestResource(exported = false)` on an entity field. For a scalar/embedded property this can hide it from being individually managed; for an association it removes the association sub-resource so clients can't traverse or modify that relationship via its dedicated link. **The association gotcha (the interview point).** SDR renders and *resolves* associations using the exported repository of the *target* type. Association values are sent/received as URIs (`text/uri-list`), e.g. to set an `Order.customer` a client PUTs `/customers/5` to `/orders/{id}/customer`. If `CustomerRepository` is `exported = false`, there is **no** `/customers/{id}` URI for SDR to emit or accept — so the `customer` link is not usable and you cannot set the association through the API. In effect, hiding a repository quietly breaks any exported association pointing at it. Symptoms include missing association links, or POSTs that can't attach the relationship. The fix is usually to keep the target repository exported (optionally hardened with projections/security) rather than fully hiding it, or to accept that the association becomes read-only/inline via a projection. **Related nuance.** `exported=false` differs from choosing a `RepositoryDetectionStrategy` (which decides the default inclusion set globally); `exported=false` is an explicit per-artifact opt-out that the DEFAULT and ANNOTATED strategies both honor. Note the ALL strategy ignores annotations and would still export a repo marked `exported=false`. **When to use.** Hide repositories that are implementation details (join tables, audit logs, lookup tables you only read internally); hide finders whose query parameters would leak data or enable enumeration; hide associations you don't want mutated over REST. Always verify that hiding a target repository doesn't strand associations from still-exported entities.
- Does exported=false remove the repository bean from the context?No. The repository (or method/field) stays fully functional in Java and injectable; only its REST endpoint is suppressed.
- You hid CustomerRepository but /orders now can't attach a customer. Why?SDR represents and sets associations using the target entity's item URI (/customers/{id}). With CustomerRepository not exported, that URI doesn't exist, so the association resource can't be resolved or modified. Keep the target exported (and secure it) or expose the value inline via a projection.
saying these in an interview costs you the question
- Thinking exported=false deletes the repository bean
- Assuming hidden target repositories don't affect associations
- Forgetting that the ALL strategy overrides exported=false