docs
Package: org.springframework.boot.origin
Provides origin tracking capabilities for properties and resources loaded by Spring Boot. Enables accurate error reporting by tracking where configuration values and resources were loaded from, including file paths, line numbers, and hierarchical origins.
The origin tracking package allows Spring Boot to track the source location of configuration properties, making error messages more helpful by showing exactly where a problematic property was defined. This is particularly useful for debugging configuration issues across multiple property files.
import org.springframework.boot.origin.*;Represents the origin of an item with support for hierarchical parent origins.
package org.springframework.boot.origin;
/**
* Interface that uniquely represents the origin of an item. For example, an item loaded
* from a File may have an origin made up of the file name along with line/column numbers.
*
* @since 2.0.0
*/
public interface Origin {
/**
* Return the parent origin for this instance if there is one.
* @return the parent origin or null
* @since 2.4.0
*/
default Origin getParent();
/**
* Find the Origin that an object originated from. Checks if the source object
* is an Origin or OriginProvider and also searches exception stacks.
* @param source the source object or null
* @return an Origin or null
*/
static Origin from(Object source);
/**
* Find the parents of the Origin that an object originated from.
* Provides a list of all parents up to root Origin.
* @param source the source object or null
* @return a list of parents or an empty list
* @since 2.4.0
*/
static List<Origin> parentsFrom(Object source);
}Functional interface for objects that can provide origin information.
package org.springframework.boot.origin;
/**
* Interface to provide access to the origin of an item.
*
* @since 2.0.0
*/
@FunctionalInterface
public interface OriginProvider {
/**
* Return the source origin or null if the origin is not known.
* @return the origin or null
*/
Origin getOrigin();
}Interface for objects that can lookup origin information by key.
package org.springframework.boot.origin;
/**
* An interface that may be implemented by an object that can lookup Origin
* information from a given key.
*
* @param <K> the lookup key type
* @since 2.0.0
*/
@FunctionalInterface
public interface OriginLookup<K> {
/**
* Return the origin of the given key or null if the origin cannot be determined.
* @param key the key to lookup
* @return the origin of the key or null
*/
Origin getOrigin(K key);
/**
* Attempt to look up the origin from the given source.
* @param source the source object
* @param key the key to lookup
* @param <K> the key type
* @return an Origin or null
*/
static <K> Origin getOrigin(Object source, K key);
}Wrapper for a value and its origin.
package org.springframework.boot.origin;
/**
* A wrapper for an Object value and Origin.
*
* @since 2.0.0
*/
public class OriginTrackedValue implements OriginProvider {
/**
* Return the tracked value.
* @return the tracked value
*/
public Object getValue();
@Override
public Origin getOrigin();
/**
* Create an OriginTrackedValue containing the specified value.
* @param value the source value
* @return an OriginTrackedValue or null if the source value was null
*/
public static OriginTrackedValue of(Object value);
/**
* Create an OriginTrackedValue containing the specified value and origin.
* @param value the source value
* @param origin the origin
* @return an OriginTrackedValue or null if the source value was null
*/
public static OriginTrackedValue of(Object value, Origin origin);
}Origin implementation for items loaded from text resources with line/column tracking.
package org.springframework.boot.origin;
/**
* Origin for an item loaded from a text resource with location information.
*
* @since 2.0.0
*/
public class TextResourceOrigin implements Origin {
public TextResourceOrigin(Resource resource, Location location);
/**
* Return the resource where the property originated.
* @return the text resource or null
*/
public Resource getResource();
/**
* Return the location of the property within the source (if known).
* @return the location or null
*/
public Location getLocation();
@Override
public Origin getParent();
/**
* Location within a text resource (line and column numbers).
*/
public static final class Location {
public Location(int line, int column);
public int getLine();
public int getColumn();
}
}Origin for properties loaded from a PropertySource.
package org.springframework.boot.origin;
/**
* Origin from a PropertySource.
*
* @since 2.0.0
*/
public class PropertySourceOrigin implements Origin {
public PropertySourceOrigin(PropertySource<?> propertySource, String propertyName);
/**
* Return the property source.
* @return the property source
*/
public PropertySource<?> getPropertySource();
/**
* Return the name of the property.
* @return the property name
*/
public String getPropertyName();
/**
* Get the origin for a property from a PropertySource.
* @param propertySource the property source
* @param name the property name
* @return the origin or null
*/
public static Origin get(PropertySource<?> propertySource, String name);
}Origin for properties from system environment variables.
package org.springframework.boot.origin;
/**
* Origin for a property loaded from the system environment.
*
* @since 2.0.0
*/
public class SystemEnvironmentOrigin extends PropertySourceOrigin {
public SystemEnvironmentOrigin(String property);
/**
* Return the original property name that was used when obtaining the value from
* the system environment (before any name conversions).
* @return the original property name
*/
public String getProperty();
}Resource implementation that tracks its origin.
package org.springframework.boot.origin;
/**
* Decorator for a Resource that also provides an Origin.
*
* @since 2.0.0
*/
public class OriginTrackedResource extends AbstractResource implements OriginProvider {
/**
* Create a new OriginTrackedResource instance.
* @param resource the resource to track (must not be null)
* @param origin the origin of the resource (may be null)
* @throws IllegalArgumentException if resource is null
*/
public OriginTrackedResource(Resource resource, Origin origin);
/**
* Return the underlying resource.
* @return the underlying resource (never null)
*/
public Resource getResource();
/**
* Return the origin of this resource.
* @return the origin or null if not known
*/
@Override
public Origin getOrigin();
// Resource interface methods - delegated to underlying resource
/**
* Return an InputStream for the content of this resource.
* Delegates to the underlying resource.
*
* @return the input stream for the underlying resource
* @throws IOException if the stream could not be opened
*/
@Override
public InputStream getInputStream() throws IOException;
/**
* Determine whether this resource actually exists in physical form.
* Delegates to the underlying resource.
*
* @return true if the resource exists
*/
@Override
public boolean exists();
/**
* Indicate whether the contents of this resource can be read.
* Delegates to the underlying resource.
*
* @return true if the resource is readable
*/
@Override
public boolean isReadable();
/**
* Indicate whether this resource represents a handle with an open stream.
* Delegates to the underlying resource.
*
* @return true if the resource represents an open stream
*/
@Override
public boolean isOpen();
/**
* Determine whether this resource represents a file in a file system.
* Delegates to the underlying resource.
*
* @return true if the resource represents a file
*/
@Override
public boolean isFile();
/**
* Return a URL handle for this resource.
* Delegates to the underlying resource.
*
* @return the URL for this resource
* @throws IOException if the resource cannot be resolved as URL
*/
@Override
public URL getURL() throws IOException;
/**
* Return a URI handle for this resource.
* Delegates to the underlying resource.
*
* @return the URI for this resource
* @throws IOException if the resource cannot be resolved as URI
*/
@Override
public URI getURI() throws IOException;
/**
* Return a File handle for this resource.
* Delegates to the underlying resource.
*
* @return the File for this resource
* @throws IOException if the resource cannot be resolved as a File
*/
@Override
public File getFile() throws IOException;
/**
* Return a ReadableByteChannel.
* Delegates to the underlying resource.
*
* @return the byte channel for the underlying resource
* @throws IOException if the channel could not be opened
*/
@Override
public ReadableByteChannel readableChannel() throws IOException;
/**
* Determine the content length for this resource.
* Delegates to the underlying resource.
*
* @return the content length in bytes
* @throws IOException if the resource cannot be resolved
*/
@Override
public long contentLength() throws IOException;
/**
* Determine the last-modified timestamp for this resource.
* Delegates to the underlying resource.
*
* @return the last-modified timestamp in milliseconds
* @throws IOException if the resource cannot be resolved
*/
@Override
public long lastModified() throws IOException;
/**
* Create a resource relative to this resource.
* Delegates to the underlying resource.
*
* @param relativePath the relative path (relative to this resource)
* @return the resource handle for the relative resource
* @throws IOException if the relative resource cannot be determined
*/
@Override
public Resource createRelative(String relativePath) throws IOException;
/**
* Determine the filename for this resource.
* Delegates to the underlying resource.
*
* @return the filename or null if this resource doesn't have a filename
*/
@Override
public String getFilename();
/**
* Return a description for this resource.
* Delegates to the underlying resource.
*
* @return a description for this resource (never null)
*/
@Override
public String getDescription();
/**
* Factory method to create an OriginTrackedResource from a Resource.
* Returns an OriginTrackedWritableResource if the source is WritableResource.
*
* @param resource the tracked resource (must not be null)
* @param origin the origin of the resource (may be null)
* @return an OriginTrackedResource or OriginTrackedWritableResource
*/
public static OriginTrackedResource of(Resource resource, Origin origin);
/**
* Factory method to create an OriginTrackedWritableResource.
*
* @param resource the tracked writable resource (must not be null)
* @param origin the origin of the resource (may be null)
* @return an OriginTrackedWritableResource
*/
public static OriginTrackedWritableResource of(WritableResource resource, Origin origin);
}import org.springframework.boot.origin.*;
// Track value with origin
TextResourceOrigin origin = new TextResourceOrigin(
new ClassPathResource("application.properties"),
new TextResourceOrigin.Location(42, 15)
);
OriginTrackedValue tracked = OriginTrackedValue.of("myValue", origin);
System.out.println("Value: " + tracked.getValue());
System.out.println("Origin: " + tracked.getOrigin());
// Output: class path resource [application.properties] - 42:15import org.springframework.boot.origin.*;
public class ConfigurationValidator {
public void validateProperty(String propertyName, Object value) {
// Check if value has origin information
Origin origin = Origin.from(value);
if (!isValid(value)) {
String message = "Invalid value for property '" + propertyName + "'";
if (origin != null) {
message += " (defined in " + origin + ")";
}
throw new IllegalArgumentException(message);
}
}
private boolean isValid(Object value) {
// Validation logic
return true;
}
}
// Example error output:
// Invalid value for property 'server.port'
// (defined in class path resource [application.properties] - 10:13)import org.springframework.boot.origin.*;
public class CustomProperty implements OriginProvider {
private final String name;
private final Object value;
private final Origin origin;
public CustomProperty(String name, Object value, Origin origin) {
this.name = name;
this.value = value;
this.origin = origin;
}
@Override
public Origin getOrigin() {
return this.origin;
}
public String getName() {
return this.name;
}
public Object getValue() {
return this.value;
}
}import org.springframework.boot.origin.*;
// Create origin hierarchy
Origin fileOrigin = new TextResourceOrigin(
new ClassPathResource("config/database.yml"),
new TextResourceOrigin.Location(25, 5)
);
// Get all parent origins
List<Origin> parents = Origin.parentsFrom(fileOrigin);
// Traverse origin hierarchy
Origin current = Origin.from(someValue);
while (current != null) {
System.out.println("Origin: " + current);
current = current.getParent();
}import org.springframework.boot.origin.*;
public class DatabaseOrigin implements Origin {
private final String tableName;
private final Long rowId;
public DatabaseOrigin(String tableName, Long rowId) {
this.tableName = tableName;
this.rowId = rowId;
}
@Override
public String toString() {
return "database table '" + tableName + "' row " + rowId;
}
@Override
public int hashCode() {
return Objects.hash(tableName, rowId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof DatabaseOrigin)) return false;
DatabaseOrigin other = (DatabaseOrigin) obj;
return Objects.equals(tableName, other.tableName) &&
Objects.equals(rowId, other.rowId);
}
}OriginTrackedValue is immutable and thread-safeOrigin tracking enables precise error messages:
Property: server.port
Value: invalid
Origin: file:/etc/myapp/application.properties:15:12
This helps developers quickly locate and fix configuration issues.Track which configuration file provided each property:
database.url from application-prod.properties:10
database.username from environment variable DATABASE_USERNAME
logging.level from application.yml:25Understand the property resolution chain when values are overridden across multiple sources.
Origin tracking is automatically used by:
@ConfigurationProperties bindingEnvironmentWhen a configuration error occurs, Spring Boot uses origin information to provide helpful error messages showing exactly where the problematic configuration was defined.