Ahmed Riyadh
01/16/2024, 1:28 PMChristopher Hübner
01/22/2024, 12:32 PMBogdan Costea
01/27/2024, 8:41 AMChristopher Hübner
01/29/2024, 11:04 AMKev
01/30/2024, 2:36 AMAnsh Tyagi
02/03/2024, 9:27 AMJavokhir Akramjonov
02/05/2024, 9:00 PMSheheryar Umair
02/06/2024, 12:58 PM@Entity
@Table(name = "\"User\"")
class User(
@Id
@Column(nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int,
@Column(nullable = false)
val name: String,
@Column(nullable = false)
val email: String,
@Column(nullable = false)
val password: String,
@Column(nullable = false)
val mobile: String,
@Column(nullable = false)
val role: String,
@Column(nullable = false)
val companyName: String,
@Column(nullable = false)
val address: String,
@Column(nullable = false)
val billingAddress: String,
@Column
val isDeleted: LocalDateTime,
)
The error I am getting is org.hibernate.InstantiationException: No default constructor for entity
. Can someone assist me to solve this.dany giguere
02/07/2024, 11:58 PM@Repository
class UserRepository(private val databaseClient: DatabaseClient) {
suspend fun findById(id: Long): User? =
databaseClient
.sql("SELECT * FROM user WHERE id = $id")
.map { row ->
User(
row.get("id") as Long,
row.get("username") as String,
row.get("email") as String,
null.toString()
)
}.awaitOneOrNull()
suspend fun create(username: String, email: String, password: String): User? =
databaseClient.sql("INSERT INTO user (username, email, password) VALUES ('$username', '$email', '$password')")
.map { row ->
User(
row.get("id") as Long,
row.get("username") as String,
row.get("email") as String,
null.toString()
)
}.awaitOneOrNull()
}
The way I have it the create function is not returning a User. Anyone how I could do that ? (maybe I’ll have to do another select query ???)Reuben
02/08/2024, 12:53 AMCoroutineCrudRepository
, but it comes with additional methods built in that I don't really need. Is there a way to use CoroutineCrudRepository
but without these additional methods?Idongesit Samuel Robson
02/08/2024, 7:11 PMdany giguere
02/10/2024, 9:14 PM@PostMapping("/posts")
suspend fun create(@Valid @RequestBody postDto: PostDto): ResponseEntity<PostDto> {
val response = postService.create(postDto)
return if (response != null) ResponseEntity.ok(response)
else ResponseEntity.notFound().build()
}
then:
@Service
class PostService(val repository: PostRepository) {
...
suspend fun create(postDto: PostDto): PostDto? =
repository.create(postDto)
and in the repo I have :
suspend fun create(postDto: PostDto): PostDto? =
databaseClient.sql("INSERT INTO posts (title, description) VALUES (:title, :description)")
.filter { statement, _ -> statement.returnGeneratedValues("id").execute() }
.bind("title", postDto.title)
.bind("description", postDto.description)
.fetch()
.first()
.map { row ->
val id = row["id"] as Long
val postEntity = postDto.toEntity().copy(id = id)
postEntity.toDto()
}
.awaitSingleOrNull()
In the controller method, I’m not sure ResponseEntity<PostDto>
is non blocking. Anyone knows ? I’m not sure my exceptionHandler nor my validator are non blocking. The code is available on this repo here: https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutinesNathan
02/11/2024, 9:49 AMdany giguere
02/11/2024, 11:22 PMspring:
r2dbc:
url: r2dbc:h2:mem:///~/db/
name: testdb
username: sa
password:
flyway:
url: jdbc:h2:mem:///~/db/testdb
user: ${spring.r2dbc.username}
password: ${spring.r2dbc.password}
baseline-on-migrate: true
Then I have in `V1_1__create_users_and_posts_tables.sql`:
CREATE TABLE IF NOT EXISTS users
(
id bigint NOT NULL AUTO_INCREMENT,
username varchar(255) NOT NULL DEFAULT '',
email varchar(255) NOT NULL DEFAULT '',
phoneNumber varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS posts
(
id bigint NOT NULL AUTO_INCREMENT,
userId bigint NOT NULL,
title varchar(255) NOT NULL DEFAULT '',
description varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
It works but it creates a PUBLIC schema:
Database: jdbc:h2:mem:///~/db/testdb (H2 2.2)
Flyway upgrade recommended: H2 2.2.224 is newer than this version of Flyway and support has not been tested. The latest supported version of H2 is 2.2.220.
Schema history table "PUBLIC"."flyway_schema_history" does not exist yet
Successfully validated 2 migrations (execution time 00:00.009s)
Creating Schema History table "PUBLIC"."flyway_schema_history" ...
Current version of schema "PUBLIC": << Empty Schema >>
Migrating schema "PUBLIC" to version "1.1 - create users and posts tables"
Migrating schema "PUBLIC" to version "2.1 - create images table"
Successfully applied 2 migrations to schema "PUBLIC", now at version v2.1 (execution time 00:00.003s)
But when I call one of my api endpoints, I see this error: Caused by: io.r2dbc.spi.R2dbcBadGrammarException: Table "USERS" not found (this database is empty);
I tried changing the testdb name for PUBLIC in my application file and creating the tables under the PUBLIC schema but I still get the same error. Any ideas anyone ? (The repo is here: https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutines)Christopher Hübner
02/12/2024, 11:58 AM@ControllerAdvice
Class, that have been thrown by Axon. For example, this dont work.
typealias SpringExceptionHandler = org.springframework.web.bind.annotation.ExceptionHandler
typealias AxonExceptionHandler = org.axonframework.messaging.interceptors.ExceptionHandler
@ControllerAdvice
class ExceptionHandler : ResponseEntityExceptionHandler() {
@SpringExceptionHandler
fun handleEventExceptions(
exception: NoHandlerForCommandException, request: WebRequest
): ResponseEntity<*> {
return handleExceptionInternal(
exception, exception.message, HttpHeaders(), HttpStatus.UNPROCESSABLE_ENTITY, request
)!!
}
@SpringExceptionHandler
fun handleCommandBusException(
exception: CommandBusException, request: WebRequest
): ResponseEntity<Any> {
return handleExceptionInternal(
exception, exception.message, HttpHeaders(), HttpStatus.UNPROCESSABLE_ENTITY, request
)!!
}
}
Exceptions are thrown, but I cant handle them within my controller with try catch, nor by a ExceptionHandler.dany giguere
02/12/2024, 10:39 PMdata class UserDto(
val id: Long?,
...
var posts: List<PostDto>? = emptyList()
)
and my post:
data class PostDto(
val id: Long?,
var userId: Long,
...
var user: UserDto? = null
)
my function was going to be this:
suspend fun findByIdWithUser(id: Long): PostDto? = coroutineScope {
val post = async{findById(id)}
val user = async{userRepository.findById(id)}
return@coroutineScope post.await()?.copy(user = user.await())
}
But it won’t compile because I get this error: Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
Ideas anyone ?Sheheryar Umair
02/14/2024, 6:55 AM@Bean
@Throws(Exception::class)
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain? {
return http.csrf { obj: CsrfConfigurer<HttpSecurity> -> obj.disable() }
.authorizeHttpRequests(
Customizer { auth: AuthorizationManagerRequestMatcherRegistry ->
auth.requestMatchers("/users/hello").permitAll()
.requestMatchers("/users/**")
.authenticated()
}
)
.httpBasic(Customizer.withDefaults()).build()
}
The error is
Type arguments should be specified for an outer class 'AuthorizeHttpRequestsConfigurer'. Use full class name to specify them
dany giguere
02/18/2024, 9:42 PM@ContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PostControllerTest(@Autowired val webTestClient: WebTestClient) {
@MockkBean
lateinit var postService: PostService
lateinit var postRepository: PostRepository
@BeforeEach
fun setUp() {
postRepository = mockk()
}
@Test
fun `GIVEN valid data WHEN a post is submitted THEN the post is returned`() {
// Given
val postDto = PostFactory(postRepository).makeOne(1)
coEvery { postService.create(1, postDto) } returns postDto
Can someone can confirm this is the right way to do it ? My concern is regarding the PostRepository. I think because of lateinit, PostRepository is not created and because I initialize it with mockk(), then it will only be mocked. Right ? : https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutines/blob/main/src/test/kotlin/com/example/demo/unit/PostControllerTest.ktdany giguere
02/25/2024, 5:06 PMSheheryar Umair
02/26/2024, 12:49 PM@Entity
class OrderFile {
@Id
@Column(nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int? = null
@Column
var fileUrl: String? = null
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
var order: Order? = null
}
@Entity
@Table(name = "orders")
class Order {
@Id
@Column(nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int? = null
@Column
var userId: Int? = null
@Column
var serviceId: Int? = null
@OneToMany(mappedBy = "order", cascade = [CascadeType.ALL], orphanRemoval = true)
var orderFiles: MutableSet<OrderFile>? = null
}
My service layer code is like this
fun createOrder(order: Order): OrderDTO {
val createdOrder=orderRepository.save(order)
return createdOrder.toOrderDTO()
}
This code saves the fileURL in OrderFile Table but the order field in the OrderFile Table remains null. The required behavior I want is that when I save this the order ID should also be reflected in the orderfield in my OrderFile Table
Any help in this regard would be appreciated!Arivnd Ramesh
02/26/2024, 5:36 PM@Observed
annotation in the new Observation API in Spring 3 working with suspended functions. I have something like this:
@Observed(contextualName = "MY SPAN NAME")
suspend fun myFunction(myArgs: String) {
// stuff happens, maybe another suspending function is called
return
}
But I'm not quite able to get the span name to show up in my APM app. I looked through the docs and have ensured all the necessary libraries exist (spring AOP, micrometer, statD registry, latest versions of all). Curious to hear if others have got this to work in their Kotlin Spring appskubele
02/28/2024, 2:24 PMsdeleuze
03/06/2024, 7:05 AMPihentagy
03/06/2024, 7:28 AMMaciej Nawrocki
03/06/2024, 4:40 PMsdeleuze
03/07/2024, 2:23 PM6.1.5-SNAPSHOT
Spring Framework builds available from https://repo.spring.io/snapshot repository with Spring Boot 3.2.3 and let me know if you identify any regression.Asif Ahmed
03/08/2024, 12:56 PMApiClient
for blocking calls. Due to certain limitations, adopting a fully reactive approach isn’t feasible at the moment. However, we are keen on finding a middle ground to improve performance through parallel calls.
To achieve this, we are exploring Kotlin Coroutines(We have also explored CompletableFuture and @Asyc but not happy with it ). As a relative newcomer to coroutines, I’ve implemented a solution that seems to work, but I’m uncertain if it’s the optimal approach. Below is a simplified snippet of the current implementation:
@Service
class Service(
private val clientA: ClientA,
private val clientB: ClientB,
private val clientC: ClientC
) {
fun someFunction(): OrderForm {
runBlocking(RequestCoroutineContext()) {
val result1 = async(Dispatchers.IO) { callA() }
val result2 = async(Dispatchers.IO) { callB() }
val result3 = async(Dispatchers.IO) { callC(result1.await()) }
OrderForm(result1.await(), result2.await(), result3.await())
}
}
private suspend fun callA() = clientA.get()
private suspend fun callB() = clientB.get()
private suspend fun callC(value: SomeType) = clientC.get(value)
}
Initially, the ApiClient
methods were not marked as suspend
, but I’m now considering moving towards making these calls suspendable to bring them closer to the client:
class ClientA {
suspend fun getA() {
withContext(Dispatchers.IO) {
// blocking API call
}
}
}
class ClientB {
suspend fun getB() {
withContext(Dispatchers.IO) {
// blocking API call
}
}
}
class ClientC {
suspend fun getC(value: SomeType) {
withContext(Dispatchers.IO) {
// blocking API call
}
}
}
However, attempting to call these suspendable functions in someFunction()
resulted in an exception
Handler dispatch failed: java.lang.NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt","stack_trace":"jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt
related to NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt
. I suspect this may be due to the fact that the actual API calls are not reactive and suspendable.
I’m seeking recommendations on the best way to handle coroutines in a single thread per request model with Spring Boot. I want to avoid marking private functions as suspended and continually wrapping code in scopes.
Any insights or guidance would be greatly appreciated.Christopher Hübner
03/12/2024, 8:25 AMEmil Kantis
03/15/2024, 12:52 PM