Skip to content

Commit 8bf93c7

Browse files
committed
Update application properties and add README generation for improved configuration and documentation
1 parent 55f95bb commit 8bf93c7

3 files changed

Lines changed: 238 additions & 66 deletions

File tree

src/main/kotlin/com/github/cnrture/quickbackendwizard/contents/ApplicationContent.kt

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@ server.port=8080
2929
server.servlet.context-path=/${projectName.lowercase()}
3030
3131
# H2 Database Configuration
32-
spring.datasource.url=jdbc:h2:mem:${'$'}{DB_NAME}
32+
spring.datasource.url=jdbc:h2:mem:${'$'}{DB_NAME:testdb}
3333
spring.datasource.driverClassName=org.h2.Driver
34-
spring.datasource.username=${'$'}{DB_USERNAME}
35-
spring.datasource.password=${'$'}{DB_PASSWORD}
34+
spring.datasource.username=${'$'}{DB_USERNAME:sa}
35+
spring.datasource.password=${'$'}{DB_PASSWORD:}
3636
spring.h2.console.enabled=true
3737
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
3838
spring.jpa.hibernate.ddl-auto=create-drop
3939
spring.jpa.show-sql=true
4040
4141
# CORS Configuration (Environment-based for security)
42-
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS}
43-
cors.allowed-methods=${'$'}{ALLOWED_METHODS}
44-
cors.allowed-headers=${'$'}{ALLOWED_HEADERS}
42+
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS:*}
43+
cors.allowed-methods=${'$'}{ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
44+
cors.allowed-headers=${'$'}{ALLOWED_HEADERS:Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since}
4545
cors.max-age=${'$'}{CORS_MAX_AGE:3600}
4646
""".trimIndent()
4747

@@ -53,18 +53,18 @@ server.port=8080
5353
server.servlet.context-path=/${projectName.lowercase().trim()}
5454
5555
# MySQL Database Configuration
56-
spring.datasource.url=jdbc:mysql://localhost:3306/${'$'}{DB_NAME}
57-
spring.datasource.username=${'$'}{DB_USERNAME}
58-
spring.datasource.password=${'$'}{DB_PASSWORD}
56+
spring.datasource.url=jdbc:mysql://localhost:3306/${'$'}{DB_NAME:testdb}
57+
spring.datasource.username=${'$'}{DB_USERNAME:root}
58+
spring.datasource.password=${'$'}{DB_PASSWORD:password}
5959
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
6060
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
6161
spring.jpa.hibernate.ddl-auto=update
6262
spring.jpa.show-sql=true
6363
6464
# CORS Configuration (Environment-based for security)
65-
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS}
66-
cors.allowed-methods=${'$'}{ALLOWED_METHODS}
67-
cors.allowed-headers=${'$'}{ALLOWED_HEADERS}
65+
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS:*}
66+
cors.allowed-methods=${'$'}{ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
67+
cors.allowed-headers=${'$'}{ALLOWED_HEADERS:Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since}
6868
cors.max-age=${'$'}{CORS_MAX_AGE:3600}
6969
""".trimIndent()
7070

@@ -76,18 +76,18 @@ server.port=8080
7676
server.servlet.context-path=/${projectName.lowercase().trim()}
7777
7878
# MariaDB Database Configuration
79-
spring.datasource.url=jdbc:mariadb://localhost:3306/${'$'}{DB_NAME}
80-
spring.datasource.username=${'$'}{DB_USERNAME}
81-
spring.datasource.password=${'$'}{DB_PASSWORD}
79+
spring.datasource.url=jdbc:mariadb://localhost:3306/${'$'}{DB_NAME:testdb}
80+
spring.datasource.username=${'$'}{DB_USERNAME:root}
81+
spring.datasource.password=${'$'}{DB_PASSWORD:password}
8282
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
8383
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
8484
spring.jpa.hibernate.ddl-auto=update
8585
spring.jpa.show-sql=true
8686
8787
# CORS Configuration (Environment-based for security)
88-
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS}
89-
cors.allowed-methods=${'$'}{ALLOWED_METHODS}
90-
cors.allowed-headers=${'$'}{ALLOWED_HEADERS}
88+
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS:*}
89+
cors.allowed-methods=${'$'}{ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
90+
cors.allowed-headers=${'$'}{ALLOWED_HEADERS:Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since}
9191
cors.max-age=${'$'}{CORS_MAX_AGE:3600}
9292
""".trimIndent()
9393

@@ -99,18 +99,18 @@ server.port=8080
9999
server.servlet.context-path=/${projectName.lowercase().trim()}
100100
101101
# PostgreSQL Database Configuration
102-
spring.datasource.url=jdbc:postgresql://localhost:5432/${'$'}{DB_NAME}
103-
spring.datasource.username=${'$'}{DB_USERNAME}
104-
spring.datasource.password=${'$'}{DB_PASSWORD}
102+
spring.datasource.url=jdbc:postgresql://localhost:5432/${'$'}{DB_NAME:testdb}
103+
spring.datasource.username=${'$'}{DB_USERNAME:postgres}
104+
spring.datasource.password=${'$'}{DB_PASSWORD:password}
105105
spring.datasource.driver-class-name=org.postgresql.Driver
106106
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
107107
spring.jpa.hibernate.ddl-auto=update
108108
spring.jpa.show-sql=true
109109
110110
# CORS Configuration (Environment-based for security)
111-
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS}
112-
cors.allowed-methods=${'$'}{ALLOWED_METHODS}
113-
cors.allowed-headers=${'$'}{ALLOWED_HEADERS}
111+
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS:*}
112+
cors.allowed-methods=${'$'}{ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
113+
cors.allowed-headers=${'$'}{ALLOWED_HEADERS:Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since}
114114
cors.max-age=${'$'}{CORS_MAX_AGE:3600}
115115
""".trimIndent()
116116

@@ -122,9 +122,9 @@ server.port=8080
122122
server.servlet.context-path=/${projectName.lowercase().trim()}
123123
124124
# CORS Configuration (Environment-based for security)
125-
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS}
126-
cors.allowed-methods=${'$'}{ALLOWED_METHODS}
127-
cors.allowed-headers=${'$'}{ALLOWED_HEADERS}
125+
cors.allowed-origins=${'$'}{ALLOWED_ORIGINS:*}
126+
cors.allowed-methods=${'$'}{ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
127+
cors.allowed-headers=${'$'}{ALLOWED_HEADERS:Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since}
128128
cors.max-age=${'$'}{CORS_MAX_AGE:3600}
129129
""".trimIndent()
130130
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package com.github.cnrture.quickbackendwizard.contents
2+
3+
fun getReadmeContent(
4+
projectName: String,
5+
selectedDatabase: String,
6+
endpoints: List<String>,
7+
) = """
8+
# $projectName
9+
10+
A Spring Boot application generated with Quick Backend Wizard.
11+
12+
## Features
13+
14+
- Spring Boot 3.3.5
15+
- Kotlin
16+
- ${selectedDatabase.uppercase()} Database
17+
${if (endpoints.isNotEmpty()) "- Generated REST APIs: ${endpoints.joinToString(", ")}" else ""}
18+
19+
## Getting Started
20+
21+
### Prerequisites
22+
23+
- Java 21 or higher
24+
- ${getDatabasePrerequisite(selectedDatabase)}
25+
26+
### Environment Configuration
27+
28+
This project uses environment variables for configuration. You can either:
29+
30+
1. **Use the provided .env file** (recommended for development):
31+
- The project includes a `.env` file with default values
32+
- Modify the values in `.env` file according to your setup
33+
34+
2. **Set environment variables manually**:
35+
```bash
36+
export DB_NAME=your_database_name
37+
export DB_USERNAME=your_username
38+
export DB_PASSWORD=your_password
39+
```
40+
41+
3. **Use default values**:
42+
- If no environment variables are set, the application will use default values:
43+
- DB_NAME: testdb
44+
- DB_USERNAME: ${getDefaultUsername(selectedDatabase)}
45+
- DB_PASSWORD: ${getDefaultPassword(selectedDatabase)}
46+
47+
### Database Setup
48+
49+
${getDatabaseSetupInstructions(selectedDatabase)}
50+
51+
### Running the Application
52+
53+
1. **Using Gradle Wrapper**:
54+
```bash
55+
./gradlew bootRun
56+
```
57+
58+
2. **Using IDE**:
59+
- Import the project as a Gradle project
60+
- Run the main application class
61+
62+
3. **Building JAR**:
63+
```bash
64+
./gradlew bootJar
65+
java -jar build/libs/$projectName-*.jar
66+
```
67+
68+
### API Endpoints
69+
70+
The application will be available at: `http://localhost:8080/$projectName`
71+
72+
${if (endpoints.isNotEmpty()) getEndpointsDocumentation(endpoints) else "No specific endpoints were generated."}
73+
74+
### Development
75+
76+
- Application properties: `src/main/resources/application.properties`
77+
- Environment variables: `.env` file in project root
78+
- Database schema: `create_tables.sql` (if applicable)
79+
80+
### Troubleshooting
81+
82+
**Database Connection Issues:**
83+
- Make sure your database server is running
84+
- Check your environment variables or .env file
85+
- Verify database credentials and connection URL
86+
87+
**Build Issues:**
88+
- Make sure you have Java 21 or higher
89+
- Clean and rebuild: `./gradlew clean build`
90+
91+
## Generated Structure
92+
93+
```
94+
$projectName/
95+
├── src/main/kotlin/
96+
│ └── [package]/
97+
│ ├── Application.kt
98+
│ ├── config/
99+
│ ├── controller/
100+
│ ├── service/
101+
│ ├── repository/
102+
│ └── entity/
103+
├── src/main/resources/
104+
│ └── application.properties
105+
├── .env
106+
├── build.gradle.kts
107+
└── README.md
108+
```
109+
""".trimIndent()
110+
111+
private fun getDatabasePrerequisite(database: String): String = when (database) {
112+
"mysql" -> "MySQL 8.0 or higher"
113+
"mariadb" -> "MariaDB 10.6 or higher"
114+
"postgresql" -> "PostgreSQL 13 or higher"
115+
"h2" -> "No additional database required (H2 embedded)"
116+
else -> "Database server"
117+
}
118+
119+
private fun getDefaultUsername(database: String): String = when (database) {
120+
"postgresql" -> "postgres"
121+
"h2" -> "sa"
122+
else -> "root"
123+
}
124+
125+
private fun getDefaultPassword(database: String): String = when (database) {
126+
"h2" -> "(empty)"
127+
else -> "password"
128+
}
129+
130+
private fun getDatabaseSetupInstructions(database: String): String = when (database) {
131+
"mysql" -> """
132+
1. Install and start MySQL server
133+
2. Create a database: `CREATE DATABASE testdb;`
134+
3. Update .env file with your MySQL credentials
135+
""".trimIndent()
136+
137+
"mariadb" -> """
138+
1. Install and start MariaDB server
139+
2. Create a database: `CREATE DATABASE testdb;`
140+
3. Update .env file with your MariaDB credentials
141+
""".trimIndent()
142+
143+
"postgresql" -> """
144+
1. Install and start PostgreSQL server
145+
2. Create a database: `CREATE DATABASE testdb;`
146+
3. Update .env file with your PostgreSQL credentials
147+
""".trimIndent()
148+
149+
"h2" -> """
150+
H2 is an embedded database - no additional setup required.
151+
You can access the H2 console at: http://localhost:8080/h2-console
152+
""".trimIndent()
153+
154+
else -> "Please refer to DATABASE_SETUP.md for detailed instructions."
155+
}
156+
157+
private fun getEndpointsDocumentation(endpoints: List<String>): String {
158+
val endpointDocs = endpoints.joinToString("\n\n") { endpoint ->
159+
val entityName = endpoint.removeSuffix("s").replaceFirstChar { it.uppercase() }
160+
"""
161+
**$entityName Management:**
162+
- GET `/$endpoint` - List all $endpoint
163+
- GET `/$endpoint/{id}` - Get ${entityName.lowercase()} by ID
164+
- POST `/$endpoint` - Create new ${entityName.lowercase()}
165+
- PUT `/$endpoint/{id}` - Update ${entityName.lowercase()}
166+
- DELETE `/$endpoint/{id}` - Delete ${entityName.lowercase()}
167+
""".trimIndent()
168+
}
169+
170+
return """
171+
Generated API endpoints:
172+
173+
$endpointDocs
174+
175+
All endpoints return JSON responses and expect JSON request bodies where applicable.
176+
""".trimIndent()
177+
}

src/main/kotlin/com/github/cnrture/quickbackendwizard/generators/QBWSpringBootModuleBuilder.kt

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class QBWSpringBootModuleBuilder : JavaModuleBuilder() {
115115
createGitIgnore(root)
116116
createApplicationProperties(root)
117117
createWebConfigFile(root)
118+
createReadmeFile(root)
118119

119120
createDatabaseFiles(root)
120121
createEnvFile(root, dbName, dbUsername, dbPassword)
@@ -128,49 +129,38 @@ class QBWSpringBootModuleBuilder : JavaModuleBuilder() {
128129
}
129130

130131
private fun createBuildGradle(root: VirtualFile) {
131-
val dependencies = mutableListOf<String>()
132-
133-
dependencies.add("implementation(\"org.springframework.boot:spring-boot-starter\")")
134-
dependencies.add("implementation(\"org.jetbrains.kotlin:kotlin-reflect\")")
135-
136-
if (includeSpringWeb) {
137-
dependencies.add("implementation(\"org.springframework.boot:spring-boot-starter-web\")")
138-
}
139-
if (includeSpringDataJpa) {
140-
dependencies.add("implementation(\"org.springframework.boot:spring-boot-starter-data-jpa\")")
141-
}
142-
when (selectedDatabase) {
143-
"h2" -> {
144-
dependencies.add("implementation(\"com.h2database:h2\")")
132+
val dependencies = StringBuilder().apply {
133+
append("implementation(\"org.springframework.boot:spring-boot-starter\")")
134+
if (includeSpringWeb) {
135+
append("\n implementation(\"org.springframework.boot:spring-boot-starter-web\")")
145136
}
146-
147-
"mysql" -> {
148-
dependencies.add("implementation(\"mysql:mysql-connector-java:8.0.33\")")
137+
if (includeSpringDataJpa) {
138+
append("\n implementation(\"org.springframework.boot:spring-boot-starter-data-jpa\")")
149139
}
150-
151-
"mariadb" -> {
152-
dependencies.add("implementation(\"org.mariadb.jdbc:mariadb-java-client:3.1.4\")")
140+
if (includeSpringSecurity) {
141+
append("\n implementation(\"org.springframework.boot:spring-boot-starter-security\")")
153142
}
154-
155-
"postgresql" -> {
156-
dependencies.add("implementation(\"org.postgresql:postgresql:42.6.0\")")
143+
if (includeValidation) {
144+
append("\n implementation(\"org.springframework.boot:spring-boot-starter-validation\")")
157145
}
158-
}
159-
if (includeSpringSecurity) {
160-
dependencies.add("implementation(\"org.springframework.boot:spring-boot-starter-security\")")
161-
}
162-
if (includeValidation) {
163-
dependencies.add("implementation(\"org.springframework.boot:spring-boot-starter-validation\")")
164-
}
165-
166-
dependencies.add("testImplementation(\"org.springframework.boot:spring-boot-starter-test\")")
167-
dependencies.add("testImplementation(\"org.jetbrains.kotlin:kotlin-test-junit5\")")
168-
dependencies.add("testImplementation(\"io.mockk:mockk:1.13.8\")")
169-
dependencies.add("testImplementation(\"io.mockk:mockk-jvm:1.13.8\")")
170-
dependencies.add("testRuntimeOnly(\"org.junit.platform:junit-platform-launcher\")")
171-
172-
val dependenciesBlock = dependencies.joinToString("\n ")
173-
val content = getGradleContent(groupId, version, dependenciesBlock, isAddGradleTasks)
146+
append("\n implementation(\"org.jetbrains.kotlin:kotlin-reflect\")")
147+
append("\n implementation(\"me.paulschwarz:spring-dotenv:4.0.0\")")
148+
append("\n\n // Database drivers")
149+
when (selectedDatabase) {
150+
"h2" -> append("\n implementation(\"com.h2database:h2\")")
151+
"mysql" -> append("\n implementation(\"mysql:mysql-connector-java:8.0.33\")")
152+
"mariadb" -> append("\n implementation(\"org.mariadb.jdbc:mariadb-java-client:3.1.4\")")
153+
"postgresql" -> append("\n implementation(\"org.postgresql:postgresql:42.6.0\")")
154+
}
155+
append("\n\n // Testing")
156+
append("\n testImplementation(\"org.springframework.boot:spring-boot-starter-test\")")
157+
append("\n testImplementation(\"org.jetbrains.kotlin:kotlin-test-junit5\")")
158+
append("\n testImplementation(\"io.mockk:mockk:1.13.8\")")
159+
append("\n testImplementation(\"io.mockk:mockk-jvm:1.13.8\")")
160+
append("\n testRuntimeOnly(\"org.junit.platform:junit-platform-launcher\")")
161+
}.toString()
162+
163+
val content = getGradleContent(groupId, version, dependencies, isAddGradleTasks)
174164
createFile(root, "build.gradle.kts", content)
175165
}
176166

@@ -343,6 +333,11 @@ class QBWSpringBootModuleBuilder : JavaModuleBuilder() {
343333
configDir?.let { createFile(it, "WebConfig.kt", content) }
344334
}
345335

336+
private fun createReadmeFile(root: VirtualFile) {
337+
val content = getReadmeContent(projectName, selectedDatabase, endpoints)
338+
createFile(root, "README.md", content)
339+
}
340+
346341
override fun createWizardSteps(
347342
wizardContext: WizardContext,
348343
modulesProvider: ModulesProvider,

0 commit comments

Comments
 (0)