Spring boot service used to execute commands triggered by REST API endpoint. It's main purpose is to act as a simple solution to run static SQL script in a separated service. Some commands (as SQL script command) are predefined, custom commands can be easily implemented.
All commands are executed within one transaction.
Service works with commands - classes that implement Cmd
. For example:
@Component
@Order(Int.MIN_VALUE)
class SqlScriptCmd(private val jdbcTemplate: JdbcTemplate) : Cmd {
override fun getName() = "SQL_SCRIPT"
override fun execute() = runScripts(loadScripts())
private fun runScripts(scripts: List<SqlScript>) {
scripts.forEach {
logger.debug("Executing script ${it.name}")
jdbcTemplate.update(it.sql)
}
}
private fun loadScripts(): List<SqlScript> {
return PathMatchingResourcePatternResolver()
.getResources("classpath:/*.sql")
.sortedBy { it.filename }
.map {
SqlScript(
name = it.filename!!,
sql = String(Files.readAllBytes(it.file.toPath()), StandardCharsets.UTF_8))
}
}
}
As seen above two methods need to be implemented:
- execute() - executes command
- getName() - defines command name
Commands are executed in order. Priorities can be configured via @Ordered
annotation.
Annotation is optional and represents an order value.
Lower values have higher priority. The default value is Ordered.LOWEST_PRECEDENCE
, indicating lowest priority (losing to any other specified order value).
@Component
@Order(1)
class MyFirstCommand : Cmd {
override fun getName() = "MY_COMMAND_1"
override fun execute() = TODO()
}
@Component
@Order(2)
class MySecondCommand : Cmd {
override fun getName() = "MY_COMMAND_2"
override fun execute() = TODO()
}
Let's say multiple commands are implemented. With properties configuration commands can easily be 'activated' or 'deactivated:
- cmd.includes - defines list of commands that are active. If property is empty all commands are active.
- cmd.excludes - defines list of commands that are excluded from execution, therefore inactive
In properties all commands are presented using the name of command defined via getName()
method, for example 'SQL_SCRIPT'
Some commands are already implemented and are ready to use.
Used to execute SQL scripts (files that end with .sql
) on classpath. Scripts are executed in alphabetical order.
Scripts on classpath (resources) are loaded by default. Additional scripts location can be added via property script.path
, for instance:
script.path=/Users/nejckorasa/my/path/to/scripts
Filtering of scripts is also supported via properties:
- script.suffix - Only runs scripts that match '*${script.suffix}.sql'
- script.prefix - Only runs scripts that match '${script.prefix}*.sql'
Suffix and prefix filters can be combined. They can be used to match scripts for specific database (oracle, mssql ...):
a-script-oracle.sql
a-script-mssql.sql
b-script-oracle.sql
b-script-mssql.sql
...
Using script.suffix=oracle
would result executing scripts ending with 'oracle'.
Let's say multiple scripts are used. With properties configuration scripts can easily be 'activated' or 'deactivated:
- script.includes - defines list of scripts that are active. If property is empty all commands are active.
- script.excludes - defines list of scripts that are excluded from execution, therefore inactive
In properties all scripts are presented using the file name a script, for instance 'script-1-oracle.sql'
Scripts can either be loaded each time before execution or only once (on application startup). This can be configured via property:
- script.always-reload
If set to true
, scripts can be dynamically added to classpath - no server restart is required!
Commands execution is triggered by REST API endpoint call:
- POST /execute
API documents via swagger UI can be accessed via /swagger-ui.html
For instance: http://localhost:8888/swagger-ui.html if you run the service locally on port 8888.
In logs, on startup...
____ _
/ ___|___ _ __ ___ _ __ ___ __ _ _ __ __| | ___ _ __
| | / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` |/ _ \ '__|
| |__| (_) | | | | | | | | | | | (_| | | | | (_| | __/ |
\____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|\___|_|
OAuth2 security is supported using JWT (Json Web Tokens). It can be enabled/disabled via spring profiles:
- no-auth - No security is enabled
- oauth2-auth - OAuth2 Security using JWT (actually JWK) (See property
security.oauth2.resource.jwk.key-set-uri
)
- Download ( really? )
- Configure maven or use the bundled version inside a project
- Modify
application.properties
file - Build project via Maven (
mvn install
) - Run created jar via (for instance)
java -jar commander-0.0.1-SNAPSHOT.jar
. You may want to run jar as a service or at least usenohup
To control the application’s service and you use a .conf file to customize its startup. The file is expected to be next to the jar file and have the same name but suffixed with .conf
rather than .jar
.
Run the service as commander.jar start
. Commands restart, stop and status are also supported.