name: General about: Bugs, enhancements, documentation, tasks. title: 'SpringBoot not aware of the Resource using along with @SpringBootApplication' labels: 'spring' assignees: ''
This is the basic springboot application that is an basic example of "https://github.com/anders-swanson/oracle-database-java-samples/blob/main/spring-resource-sample/pom.xml"
So using @Value inside the (along with) @SpringBootApplication, Resource is not awared of it. With seperate class, it works as expected. The code is below so anyone can reproduce it.
@Component
internal class DatabaseResourceResolver(
private val jdbcClient: JdbcClient,
@Value("\${databaseResource.table:spring_resource}") val table: String,
@Value("\${databaseResource.blobColumn:file_data}") val blobColumn: String,
@Value("\${databaseResource.fileNameColumn:file_name}") val fileNameColumn: String
): ResourceLoaderAware, ProtocolResolver {
override fun resolve(location: String, resourceLoader: ResourceLoader): Resource? {
if (location.startsWith(PROTOCOL_PREFIX)) {
val fileName: String = location.substring(PROTOCOL_PREFIX.length)
return DatabaseResource(jdbcClient = jdbcClient, table = table, blobColumn = blobColumn,
fileName = fileName, fileNameColumn = fileNameColumn)
}
return null
}
override fun setResourceLoader(resourceLoader: ResourceLoader) {
if (DefaultResourceLoader::class.java.isAssignableFrom(resourceLoader.javaClass)) {
(resourceLoader as DefaultResourceLoader).addProtocolResolver(this)
}
}
}
class DatabaseResource(
private val jdbcClient: JdbcClient,
private val table: String,
private val blobColumn: String,
private val fileNameColumn: String,
private val fileName: String
) : AbstractResource() {
override fun getInputStream(): InputStream = content.inputStream()
override fun contentLength(): Long = content.size.toLong()
override fun exists(): Boolean =
jdbcClient
.sql(query)
.query { rs: ResultSet, _: Int -> rs.next() }
.single()
override fun getDescription(): String = "{$PROTOCOL_PREFIX}$table/$fileName"
override fun getFilename(): String = fileName
private val content: ByteArray by lazy {
jdbcClient
.sql(query)
.query { rs: ResultSet, _: Int -> rs.getBinaryStream(blobColumn).readAllBytes() }
.single()
}
private val query: String = "select $blobColumn from $table where $fileNameColumn = '$fileName'"
companion object {
const val PROTOCOL_PREFIX: String = "postgresql://"
}
}
So following will work;
@RestController
class SpringBootApplicationController(
@Value("postgresql://cat.jpg") private val resource: Resource
) {
@GetMapping("/cat")
fun cat(): Resource = resource
@GetMapping("/isCat")
fun isCat(): Boolean = resource.exists()
}
But following will not aware of the Resource;
@SpringBootApplication
@RestController
class SpringKotlinResourceLoaderApplication(
@Value("postgresql://cat.jpg") private val resource: Resource
){
@GetMapping("/cat")
fun cat(): Resource = resource
@GetMapping("/isCat")
fun isCat(): Boolean = resource.exists()
}
Db is basically 1 table(2 columns file_name and file_data) in postgresql
create table if not exists spring_resource (
file_name varchar(500) not null primary key,
file_data bytea not null
)
https://stackoverflow.com/questions/79395014/springboot-not-aware-of-the-resource-using-along-with-springbootapplication