Task: Upgraded the dgs graphql to submodules and parent modules for extends projects
This commit is contained in:
37
dgs-graphql/.gitignore
vendored
Normal file
37
dgs-graphql/.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
../HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
44
dgs-graphql/build.gradle.kts
Normal file
44
dgs-graphql/build.gradle.kts
Normal file
@@ -0,0 +1,44 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
id("org.springframework.boot")
|
||||
id("io.spring.dependency-management")
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.spring")
|
||||
kotlin("plugin.jpa")
|
||||
id("com.netflix.dgs.codegen")
|
||||
}
|
||||
|
||||
extra["dgsVersion"] = "4.5.0"
|
||||
|
||||
dependencies {
|
||||
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:${property("dgsVersion")}")
|
||||
runtimeOnly("com.netflix.graphql.dgs:graphql-dgs-subscriptions-websockets-autoconfigure:${property("dgsVersion")}")
|
||||
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-actuator")
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
||||
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
|
||||
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||
runtimeOnly("org.postgresql:postgresql")
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("io.projectreactor:reactor-test")
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
tasks.withType<com.netflix.graphql.dgs.codegen.gradle.GenerateJavaTask> {
|
||||
packageName = "com.cubetiqs.graphql.demo.dgmodel"
|
||||
schemaPaths = mutableListOf("${projectDir}/src/main/resources/schema")
|
||||
generateClient = true
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.cubetiqs.graphql.demo
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
|
||||
@SpringBootApplication
|
||||
class GraphqlDemoApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<GraphqlDemoApplication>(*args)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.cubetiqs.graphql.demo.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
class GraphQLConfig
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cubetiqs.graphql.demo.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
class ManagementConfig
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.cubetiqs.graphql.demo.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
override fun addCorsMappings(corsRegistry: CorsRegistry) {
|
||||
println("Hello World")
|
||||
corsRegistry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("*")
|
||||
.maxAge(3600)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cubetiqs.graphql.demo.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.http.SessionCreationPolicy
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
override fun configure(http: HttpSecurity) {
|
||||
http.csrf().disable()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.anyRequest()
|
||||
.permitAll()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cubetiqs.graphql.demo.context
|
||||
|
||||
import com.netflix.graphql.dgs.DgsComponent
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@DgsComponent
|
||||
annotation class GMutation
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cubetiqs.graphql.demo.context
|
||||
|
||||
import com.netflix.graphql.dgs.DgsComponent
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@DgsComponent
|
||||
annotation class GQuery
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cubetiqs.graphql.demo.context
|
||||
|
||||
import com.netflix.graphql.dgs.DgsComponent
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@DgsComponent
|
||||
annotation class GSubscription
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cubetiqs.graphql.demo.domain
|
||||
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener
|
||||
import java.io.Serializable
|
||||
import javax.persistence.EntityListeners
|
||||
import javax.persistence.MappedSuperclass
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener::class)
|
||||
abstract class AbstractEntity<T, ID : Serializable> : Serializable
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.cubetiqs.graphql.demo.domain
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
abstract class AbstractInput<T> : Serializable
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
import com.cubetiqs.graphql.demo.domain.AbstractEntity
|
||||
import com.cubetiqs.graphql.demo.domain.user.User
|
||||
import com.fasterxml.jackson.annotation.JsonBackReference
|
||||
import org.hibernate.Hibernate
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.LastModifiedDate
|
||||
import java.math.BigDecimal
|
||||
import java.util.*
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "accounts", indexes = [
|
||||
Index(name = "idx_account_code", columnList = "code")
|
||||
])
|
||||
@EntityListeners(value = [AccountEntityListener::class])
|
||||
open class Account(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
open var id: Long? = null,
|
||||
|
||||
@Column(length = 9)
|
||||
open var code: String? = null,
|
||||
|
||||
@Column
|
||||
open var balance: BigDecimal = BigDecimal.ZERO,
|
||||
|
||||
@Column
|
||||
open var currentBalance: BigDecimal = BigDecimal.ZERO,
|
||||
|
||||
@Column(length = 10)
|
||||
@Enumerated(EnumType.STRING)
|
||||
open var type: AccountType = AccountType.BASIC,
|
||||
|
||||
@Column(length = 3)
|
||||
@Enumerated(EnumType.STRING)
|
||||
open var currency: AccountCurrency = AccountCurrency.USD,
|
||||
|
||||
@Version
|
||||
open var version: Long? = null,
|
||||
|
||||
@CreatedDate
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
open var createdDate: Date? = null,
|
||||
|
||||
@LastModifiedDate
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
open var updatedDate: Date? = null,
|
||||
|
||||
@JsonBackReference
|
||||
@ManyToOne(fetch = FetchType.LAZY,cascade = [CascadeType.REFRESH, CascadeType.DETACH])
|
||||
@JoinColumn(name = "user_id")
|
||||
open var user: User? = null,
|
||||
) : AbstractEntity<Account, Long>() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
|
||||
other as Account
|
||||
|
||||
return id != null && id == other.id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = 2083479647
|
||||
|
||||
@Override
|
||||
override fun toString(): String {
|
||||
return this::class.simpleName + "(id = $id , balance = $balance , currentBalance = $currentBalance , type = $type , currency = $currency , version = $version , createdDate = $createdDate , updatedDate = $updatedDate , user = ${user?.id} )"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
enum class AccountCurrency {
|
||||
USD,
|
||||
KHR,
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
import java.util.*
|
||||
import javax.persistence.PostPersist
|
||||
import javax.persistence.PrePersist
|
||||
import javax.persistence.PreUpdate
|
||||
|
||||
class AccountEntityListener {
|
||||
@PrePersist
|
||||
fun beforeSave(account: Account) {
|
||||
if (account.createdDate == null) {
|
||||
account.createdDate = Date()
|
||||
}
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
fun beforeUpdate(account: Account) {
|
||||
account.updatedDate = Date()
|
||||
}
|
||||
|
||||
@PostPersist
|
||||
fun afterSaved(account: Account) {
|
||||
account.code = account.id.toString().padStart(9, '0')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
data class AccountInput(
|
||||
var userId: Long? = null,
|
||||
var type: AccountType? = null,
|
||||
var currency: AccountCurrency? = null,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
object AccountMapper {
|
||||
fun fromInputToAccount(input: AccountInput): Account {
|
||||
return Account(
|
||||
type = input.type ?: AccountType.BASIC,
|
||||
currency = input.currency ?: AccountCurrency.USD,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cubetiqs.graphql.demo.domain.account
|
||||
|
||||
enum class AccountType {
|
||||
BASIC,
|
||||
PREMIUM,
|
||||
BUSINESS,
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.cubetiqs.graphql.demo.domain.user
|
||||
|
||||
import com.cubetiqs.graphql.demo.domain.AbstractEntity
|
||||
import com.cubetiqs.graphql.demo.domain.account.Account
|
||||
import com.fasterxml.jackson.annotation.JsonManagedReference
|
||||
import org.hibernate.Hibernate
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.LastModifiedDate
|
||||
import java.util.*
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
name = "users", indexes = [
|
||||
Index(name = "idx_user_code", columnList = "code"),
|
||||
Index(name = "idx_user_username", columnList = "username"),
|
||||
]
|
||||
)
|
||||
@EntityListeners(value = [UserEntityListener::class])
|
||||
open class User(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
open var id: Long? = null,
|
||||
|
||||
@Column(unique = true, length = 65, nullable = false)
|
||||
open var code: String? = null,
|
||||
|
||||
@Column(unique = true, length = 35, nullable = false)
|
||||
open var username: String? = null,
|
||||
|
||||
@Column(length = 100)
|
||||
open var password: String? = null,
|
||||
|
||||
@Column(length = 50)
|
||||
open var name: String? = null,
|
||||
|
||||
@Version
|
||||
open var version: Long? = null,
|
||||
|
||||
@CreatedDate
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
open var createdDate: Date? = null,
|
||||
|
||||
@LastModifiedDate
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
open var updatedDate: Date? = null,
|
||||
|
||||
@JsonManagedReference
|
||||
@OneToMany(fetch = FetchType.LAZY,mappedBy = "user", cascade = [CascadeType.ALL], orphanRemoval = true)
|
||||
open var accounts: MutableSet<Account> = mutableSetOf(),
|
||||
|
||||
@Basic
|
||||
open var enabled: Boolean = true,
|
||||
) : AbstractEntity<User, Long>() {
|
||||
@Transient
|
||||
fun updatePassword(newPassword: String) {
|
||||
// hash it here
|
||||
this.password = newPassword
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
|
||||
other as User
|
||||
|
||||
return id != null && id == other.id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = 562048007
|
||||
|
||||
@Override
|
||||
override fun toString(): String {
|
||||
return this::class.simpleName + "(id = $id , code = $code , username = $username , password = $password , name = $name , version = $version , createdDate = $createdDate , updatedDate = $updatedDate , enabled = $enabled )"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cubetiqs.graphql.demo.domain.user
|
||||
|
||||
import java.util.*
|
||||
import javax.persistence.PrePersist
|
||||
import javax.persistence.PreUpdate
|
||||
|
||||
class UserEntityListener {
|
||||
@PrePersist
|
||||
fun beforeSave(user: User) {
|
||||
user.id = null
|
||||
user.code = UUID.randomUUID().toString()
|
||||
|
||||
if (user.createdDate == null) {
|
||||
user.createdDate = Date()
|
||||
}
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
fun beforeUpdate(user: User) {
|
||||
user.updatedDate = Date()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cubetiqs.graphql.demo.domain.user
|
||||
|
||||
import com.cubetiqs.graphql.demo.domain.AbstractInput
|
||||
|
||||
data class UserInput(
|
||||
val username: String? = null,
|
||||
val password: String? = null,
|
||||
val name: String? = null,
|
||||
val enabled: Boolean? = null,
|
||||
) : AbstractInput<UserInput>()
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cubetiqs.graphql.demo.domain.user
|
||||
|
||||
object UserMapper {
|
||||
fun fromInputToUser(input: UserInput): User {
|
||||
return User(
|
||||
username = input.username,
|
||||
password = input.password,
|
||||
name = input.name,
|
||||
enabled = input.enabled ?: true,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cubetiqs.graphql.demo.repository
|
||||
|
||||
import com.cubetiqs.graphql.demo.domain.account.Account
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface AccountRepository : JpaRepository<Account, Long>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.cubetiqs.graphql.demo.repository
|
||||
|
||||
import com.cubetiqs.graphql.demo.domain.user.User
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.data.jpa.repository.Query
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface UserRepository : JpaRepository<User, Long> {
|
||||
@Query("select u from User u where u.enabled = true")
|
||||
fun queryAllByEnabledIsTrue(pageable: Pageable): Page<User>
|
||||
|
||||
@Query("select (count(u) > 0) from User u where u.username = ?1")
|
||||
fun existsAllByUsername(username: String): Boolean
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.mutation
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GMutation
|
||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||
import com.cubetiqs.graphql.demo.domain.account.Account
|
||||
import com.cubetiqs.graphql.demo.domain.account.AccountInput
|
||||
import com.cubetiqs.graphql.demo.domain.account.AccountMapper
|
||||
import com.cubetiqs.graphql.demo.repository.AccountRepository
|
||||
import com.cubetiqs.graphql.demo.repository.UserRepository
|
||||
import com.netflix.graphql.dgs.DgsMutation
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.transaction.annotation.Propagation
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@GMutation
|
||||
class AccountMutationResolver {
|
||||
@Autowired
|
||||
private lateinit var accountRepository: AccountRepository
|
||||
|
||||
@Autowired
|
||||
private lateinit var userRepository: UserRepository
|
||||
|
||||
@DgsMutation(field = DgsConstants.MUTATION.OpenAccount)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
fun openAccount(input: AccountInput): Account {
|
||||
val account = AccountMapper.fromInputToAccount(input)
|
||||
val user = userRepository.findById(input.userId ?: 0).orElse(null)
|
||||
?: throw Exception("User not found to open an account!")
|
||||
account.user = user
|
||||
return accountRepository.save(account)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.mutation
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GMutation
|
||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||
import com.cubetiqs.graphql.demo.domain.user.User
|
||||
import com.cubetiqs.graphql.demo.domain.user.UserInput
|
||||
import com.cubetiqs.graphql.demo.domain.user.UserMapper
|
||||
import com.cubetiqs.graphql.demo.repository.UserRepository
|
||||
import com.netflix.graphql.dgs.DgsMutation
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.transaction.annotation.Propagation
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@GMutation
|
||||
class UserMutationResolver @Autowired constructor(
|
||||
private val userRepository: UserRepository,
|
||||
) {
|
||||
@DgsMutation(field = DgsConstants.MUTATION.CreateUser)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
fun createUser(input: UserInput): User {
|
||||
if (userRepository.existsAllByUsername(input.username ?: "")) throw Exception("Username has been already existed!")
|
||||
|
||||
val user = UserMapper.fromInputToUser(input)
|
||||
return userRepository.save(user)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.query
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GQuery
|
||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||
import com.cubetiqs.graphql.demo.domain.account.Account
|
||||
import com.cubetiqs.graphql.demo.repository.AccountRepository
|
||||
import com.netflix.graphql.dgs.DgsQuery
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.data.domain.Pageable
|
||||
|
||||
@GQuery
|
||||
class AccountQueryResolver @Autowired constructor(
|
||||
private val accountRepository: AccountRepository,
|
||||
) {
|
||||
@DgsQuery(field = DgsConstants.QUERY.FetchAccounts)
|
||||
fun fetchAccounts(): Collection<Account> {
|
||||
val accounts = accountRepository.findAll(Pageable.unpaged())
|
||||
return accounts.content
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.query
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GQuery
|
||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||
import com.netflix.graphql.dgs.DgsQuery
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import reactor.core.publisher.Mono
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@GQuery
|
||||
class HelloQueryResolver {
|
||||
@DgsQuery(field = "hello")
|
||||
fun hello(): CompletableFuture<String> {
|
||||
return Mono.just("Hello Query...!").toFuture()
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN')")
|
||||
@DgsQuery(field = DgsConstants.QUERY.HelloByName)
|
||||
fun helloByName(name: String): CompletableFuture<String> {
|
||||
return Mono.just("Hello $name...!").toFuture()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.query
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GQuery
|
||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||
import com.cubetiqs.graphql.demo.domain.user.User
|
||||
import com.cubetiqs.graphql.demo.repository.UserRepository
|
||||
import com.netflix.graphql.dgs.DgsQuery
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.data.domain.Pageable
|
||||
|
||||
@GQuery
|
||||
class UserQueryResolver @Autowired constructor(
|
||||
private val userRepository: UserRepository,
|
||||
) {
|
||||
@DgsQuery(field = DgsConstants.QUERY.FetchUsers)
|
||||
fun fetchUsers(): Collection<User> {
|
||||
val users = userRepository.queryAllByEnabledIsTrue(Pageable.unpaged())
|
||||
return users.content
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cubetiqs.graphql.demo.resolver.subscription
|
||||
|
||||
import com.cubetiqs.graphql.demo.context.GSubscription
|
||||
import com.netflix.graphql.dgs.DgsSubscription
|
||||
import graphql.schema.DataFetchingEnvironment
|
||||
import org.reactivestreams.Publisher
|
||||
import reactor.core.publisher.Flux
|
||||
import java.time.Duration
|
||||
|
||||
@GSubscription
|
||||
class HelloSubscriptionResolver {
|
||||
@DgsSubscription(field = "hello")
|
||||
fun hello(env: DataFetchingEnvironment): Publisher<Int> {
|
||||
return Flux.range(1, 10).delayElements(Duration.ofSeconds(1))
|
||||
}
|
||||
}
|
||||
33
dgs-graphql/src/main/resources/application.yml
Normal file
33
dgs-graphql/src/main/resources/application.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
# Spring Boot
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://${DB_HOST:localhost}:5432/${DB_NAME:graphql-demo}
|
||||
username: ${DB_USER:your-username}
|
||||
password: ${DB_PASSWORD:your-password}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
jpa:
|
||||
database: postgresql
|
||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||
hibernate:
|
||||
ddl-auto: ${HIBERNATE_DDL:update}
|
||||
show-sql: ${JPA_SHOW_SQL:true}
|
||||
properties:
|
||||
hibernate:
|
||||
enable_lazy_load_no_trans: ${HIBERNATE_LAZY_NO_TRANS:true}
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
# Spring Boot Actuator
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info,metrics
|
||||
|
||||
# DGS GraphQL
|
||||
dgs:
|
||||
graphql:
|
||||
graphiql:
|
||||
enabled: true
|
||||
26
dgs-graphql/src/main/resources/schema/account.graphql
Normal file
26
dgs-graphql/src/main/resources/schema/account.graphql
Normal file
@@ -0,0 +1,26 @@
|
||||
enum AccountType {
|
||||
BASIC
|
||||
PREMIUM
|
||||
BUSINESS
|
||||
}
|
||||
|
||||
enum AccountCurrency {
|
||||
USD
|
||||
KHR
|
||||
}
|
||||
|
||||
type Account {
|
||||
id: ID
|
||||
code: String
|
||||
balance: Float
|
||||
currentBalance: Float
|
||||
type: AccountType
|
||||
currency: AccountCurrency
|
||||
user: User!
|
||||
}
|
||||
|
||||
input AccountInput {
|
||||
userId: Int
|
||||
type: AccountType
|
||||
currency: AccountCurrency
|
||||
}
|
||||
16
dgs-graphql/src/main/resources/schema/expense.graphql
Normal file
16
dgs-graphql/src/main/resources/schema/expense.graphql
Normal file
@@ -0,0 +1,16 @@
|
||||
input ExpenseFilter {
|
||||
isIncome: Boolean
|
||||
}
|
||||
|
||||
type Expense {
|
||||
id: ID
|
||||
description: String
|
||||
amount: Int
|
||||
isIncome: Boolean
|
||||
}
|
||||
|
||||
type ExpensePage {
|
||||
list: [Expense]
|
||||
totalPages: Int
|
||||
currentPage: Int
|
||||
}
|
||||
21
dgs-graphql/src/main/resources/schema/schema.graphqls
Normal file
21
dgs-graphql/src/main/resources/schema/schema.graphqls
Normal file
@@ -0,0 +1,21 @@
|
||||
type Query {
|
||||
hello: String
|
||||
|
||||
helloByName(name: String!): String
|
||||
|
||||
fetchUsers: [User]!
|
||||
|
||||
fetchAccounts: [Account]!
|
||||
|
||||
fetchExpenses(filter: ExpenseFilter, pageNumber: Int, pageSize: Int) : ExpensePage
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
hello: Int
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createUser(input: UserInput): User!
|
||||
|
||||
openAccount(input: AccountInput): Account!
|
||||
}
|
||||
14
dgs-graphql/src/main/resources/schema/user.graphql
Normal file
14
dgs-graphql/src/main/resources/schema/user.graphql
Normal file
@@ -0,0 +1,14 @@
|
||||
type User {
|
||||
id: ID
|
||||
code: String
|
||||
username: String
|
||||
name: String
|
||||
enabled: Boolean
|
||||
}
|
||||
|
||||
input UserInput {
|
||||
username: String
|
||||
password: String
|
||||
name: String
|
||||
enabled: Boolean
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.cubetiqs.graphql.demo
|
||||
|
||||
import com.cubetiqs.graphql.demo.resolver.subscription.HelloSubscriptionResolver
|
||||
import com.netflix.graphql.dgs.DgsQueryExecutor
|
||||
import com.netflix.graphql.dgs.autoconfig.DgsAutoConfiguration
|
||||
import graphql.ExecutionResult
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.reactivestreams.Publisher
|
||||
import org.reactivestreams.Subscriber
|
||||
import org.reactivestreams.Subscription
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
|
||||
@SpringBootTest(
|
||||
classes = [
|
||||
DgsAutoConfiguration::class,
|
||||
HelloSubscriptionResolver::class,
|
||||
]
|
||||
)
|
||||
class GraphqlDemoApplicationTests {
|
||||
@Autowired
|
||||
lateinit var dgsQueryExecutor: DgsQueryExecutor
|
||||
|
||||
@Test
|
||||
fun helloSubscription() {
|
||||
dgsQueryExecutor.execute(
|
||||
"""
|
||||
subscription {
|
||||
hello
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
.getData<Publisher<ExecutionResult>>()
|
||||
.subscribe(object : Subscriber<ExecutionResult> {
|
||||
override fun onSubscribe(s: Subscription) {
|
||||
s.request(2)
|
||||
}
|
||||
|
||||
override fun onNext(t: ExecutionResult) {
|
||||
println(t.getData<Any?>())
|
||||
}
|
||||
|
||||
override fun onError(t: Throwable?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
println("Hello World")
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user