diff --git a/ai/logs/ai.log b/ai/logs/ai.log index 333e047..bccff22 100644 --- a/ai/logs/ai.log +++ b/ai/logs/ai.log @@ -296,3 +296,485 @@ This generated password is for development use only. Your security configuration 2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' 2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated... 2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed. +2025-10-23 17:10:12 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 43825 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai) +2025-10-23 17:10:12 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8 +2025-10-23 17:10:12 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "dev" +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces. +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2025-10-23 17:10:12 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces. +2025-10-23 17:10:13 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8083 (http) +2025-10-23 17:10:13 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat] +2025-10-23 17:10:13 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24] +2025-10-23 17:10:13 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext +2025-10-23 17:10:13 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 668 ms +2025-10-23 17:10:13 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] +2025-10-23 17:10:13 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final +2025-10-23 17:10:13 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@66716959 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@66716959 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Boolean -> org.hibernate.type.BasicTypeReference@66716959 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration numeric_boolean -> org.hibernate.type.BasicTypeReference@34e07e65 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.NumericBooleanConverter -> org.hibernate.type.BasicTypeReference@34e07e65 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration true_false -> org.hibernate.type.BasicTypeReference@7ca0166c +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.TrueFalseConverter -> org.hibernate.type.BasicTypeReference@7ca0166c +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration yes_no -> org.hibernate.type.BasicTypeReference@1dcad16f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.YesNoConverter -> org.hibernate.type.BasicTypeReference@1dcad16f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@701c482e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@701c482e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Byte -> org.hibernate.type.BasicTypeReference@701c482e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary -> org.hibernate.type.BasicTypeReference@4738131e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte[] -> org.hibernate.type.BasicTypeReference@4738131e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [B -> org.hibernate.type.BasicTypeReference@4738131e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary_wrapper -> org.hibernate.type.BasicTypeReference@3b576ee3 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-binary -> org.hibernate.type.BasicTypeReference@3b576ee3 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration image -> org.hibernate.type.BasicTypeReference@705d914f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration blob -> org.hibernate.type.BasicTypeReference@6212ea52 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Blob -> org.hibernate.type.BasicTypeReference@6212ea52 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob -> org.hibernate.type.BasicTypeReference@65b5b5ed +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob_wrapper -> org.hibernate.type.BasicTypeReference@6595ffce +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@795eddda +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@795eddda +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Short -> org.hibernate.type.BasicTypeReference@795eddda +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration integer -> org.hibernate.type.BasicTypeReference@c6bf8d9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration int -> org.hibernate.type.BasicTypeReference@c6bf8d9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Integer -> org.hibernate.type.BasicTypeReference@c6bf8d9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@44392e64 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@44392e64 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Long -> org.hibernate.type.BasicTypeReference@44392e64 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@e18d2a2 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@e18d2a2 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Float -> org.hibernate.type.BasicTypeReference@e18d2a2 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@1a77eb6 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@1a77eb6 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Double -> org.hibernate.type.BasicTypeReference@1a77eb6 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_integer -> org.hibernate.type.BasicTypeReference@52d9f36b +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigInteger -> org.hibernate.type.BasicTypeReference@52d9f36b +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_decimal -> org.hibernate.type.BasicTypeReference@5f9ebd5a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigDecimal -> org.hibernate.type.BasicTypeReference@5f9ebd5a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character -> org.hibernate.type.BasicTypeReference@175bf9c9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char -> org.hibernate.type.BasicTypeReference@175bf9c9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Character -> org.hibernate.type.BasicTypeReference@175bf9c9 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character_nchar -> org.hibernate.type.BasicTypeReference@2db3675a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration string -> org.hibernate.type.BasicTypeReference@306c9b2c +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.String -> org.hibernate.type.BasicTypeReference@306c9b2c +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nstring -> org.hibernate.type.BasicTypeReference@1ab28416 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration characters -> org.hibernate.type.BasicTypeReference@52efb338 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char[] -> org.hibernate.type.BasicTypeReference@52efb338 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [C -> org.hibernate.type.BasicTypeReference@52efb338 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-characters -> org.hibernate.type.BasicTypeReference@64508788 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration text -> org.hibernate.type.BasicTypeReference@30b1c5d5 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ntext -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration clob -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Clob -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nclob -> org.hibernate.type.BasicTypeReference@71f8ce0e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.NClob -> org.hibernate.type.BasicTypeReference@71f8ce0e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob -> org.hibernate.type.BasicTypeReference@4fd92289 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_char_array -> org.hibernate.type.BasicTypeReference@1a8e44fe +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_character_array -> org.hibernate.type.BasicTypeReference@287317df +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_character_array -> org.hibernate.type.BasicTypeReference@1987807b +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_char_array -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDateTime -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDateTime -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDate -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDate -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalTime -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalTime -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@2b464384 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> org.hibernate.type.BasicTypeReference@77f7352a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> org.hibernate.type.BasicTypeReference@77f7352a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeUtc -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithTimezone -> org.hibernate.type.BasicTypeReference@571db8b4 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@65a2755e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> org.hibernate.type.BasicTypeReference@2b3242a5 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> org.hibernate.type.BasicTypeReference@2b3242a5 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@11120583 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration date -> org.hibernate.type.BasicTypeReference@5d8e4fa8 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Date -> org.hibernate.type.BasicTypeReference@5d8e4fa8 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration time -> org.hibernate.type.BasicTypeReference@649009d6 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Time -> org.hibernate.type.BasicTypeReference@649009d6 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timestamp -> org.hibernate.type.BasicTypeReference@652f26da +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Timestamp -> org.hibernate.type.BasicTypeReference@652f26da +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Date -> org.hibernate.type.BasicTypeReference@652f26da +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Calendar -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.GregorianCalendar -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_date -> org.hibernate.type.BasicTypeReference@6796a873 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_time -> org.hibernate.type.BasicTypeReference@3acc3ee +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration instant -> org.hibernate.type.BasicTypeReference@1f293cb7 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Instant -> org.hibernate.type.BasicTypeReference@1f293cb7 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.UUID -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration pg-uuid -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-binary -> org.hibernate.type.BasicTypeReference@5790cbcb +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-char -> org.hibernate.type.BasicTypeReference@32c6d164 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration class -> org.hibernate.type.BasicTypeReference@645c9f0f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Class -> org.hibernate.type.BasicTypeReference@645c9f0f +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration currency -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Currency -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Currency -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration locale -> org.hibernate.type.BasicTypeReference@999cd18 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Locale -> org.hibernate.type.BasicTypeReference@999cd18 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration serializable -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.io.Serializable -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timezone -> org.hibernate.type.BasicTypeReference@df432ec +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.TimeZone -> org.hibernate.type.BasicTypeReference@df432ec +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZoneOffset -> org.hibernate.type.BasicTypeReference@6144e499 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZoneOffset -> org.hibernate.type.BasicTypeReference@6144e499 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration url -> org.hibernate.type.BasicTypeReference@26f204a4 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.net.URL -> org.hibernate.type.BasicTypeReference@26f204a4 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration vector -> org.hibernate.type.BasicTypeReference@28295554 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration row_version -> org.hibernate.type.BasicTypeReference@4e671ef +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration object -> org.hibernate.type.JavaObjectType@2aac6fa7 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@2aac6fa7 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration null -> org.hibernate.type.NullType@2358443e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_date -> org.hibernate.type.BasicTypeReference@25e796fe +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_time -> org.hibernate.type.BasicTypeReference@29ba63f0 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_timestamp -> org.hibernate.type.BasicTypeReference@4822ab4d +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar -> org.hibernate.type.BasicTypeReference@516b84d1 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_date -> org.hibernate.type.BasicTypeReference@1ad1f167 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_time -> org.hibernate.type.BasicTypeReference@608eb42e +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_binary -> org.hibernate.type.BasicTypeReference@3d2b13b1 +2025-10-23 17:10:13 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_serializable -> org.hibernate.type.BasicTypeReference@30eb55c9 +2025-10-23 17:10:13 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer +2025-10-23 17:10:13 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... +2025-10-23 17:10:14 [main] WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata +java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null + at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) + at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20) +2025-10-23 17:10:14 [main] ERROR o.s.o.j.LocalContainerEntityManagerFactoryBean - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) +2025-10-23 17:10:14 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) +2025-10-23 17:10:14 [main] INFO o.a.catalina.core.StandardService - Stopping service [Tomcat] +2025-10-23 17:10:14 [main] INFO o.s.b.a.l.ConditionEvaluationReportLogger - + +Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. +2025-10-23 17:10:14 [main] ERROR o.s.boot.SpringApplication - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) + at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) + ... 15 common frames omitted +Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:191) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentWithDefaults(JdbcEnvironmentInitiator.java:152) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:362) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) + ... 30 common frames omitted +2025-10-23 17:38:09 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 49971 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai) +2025-10-23 17:38:09 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8 +2025-10-23 17:38:09 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "dev" +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 4 ms. Found 0 JPA repository interfaces. +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2025-10-23 17:38:09 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces. +2025-10-23 17:38:09 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8083 (http) +2025-10-23 17:38:09 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat] +2025-10-23 17:38:09 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24] +2025-10-23 17:38:09 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext +2025-10-23 17:38:09 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 679 ms +2025-10-23 17:38:10 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] +2025-10-23 17:38:10 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final +2025-10-23 17:38:10 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@306c9b2c +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@306c9b2c +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Boolean -> org.hibernate.type.BasicTypeReference@306c9b2c +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration numeric_boolean -> org.hibernate.type.BasicTypeReference@1ab28416 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.NumericBooleanConverter -> org.hibernate.type.BasicTypeReference@1ab28416 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration true_false -> org.hibernate.type.BasicTypeReference@52efb338 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.TrueFalseConverter -> org.hibernate.type.BasicTypeReference@52efb338 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration yes_no -> org.hibernate.type.BasicTypeReference@64508788 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.YesNoConverter -> org.hibernate.type.BasicTypeReference@64508788 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@30b1c5d5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@30b1c5d5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Byte -> org.hibernate.type.BasicTypeReference@30b1c5d5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte[] -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [B -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary_wrapper -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-binary -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration image -> org.hibernate.type.BasicTypeReference@71f8ce0e +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration blob -> org.hibernate.type.BasicTypeReference@4fd92289 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Blob -> org.hibernate.type.BasicTypeReference@4fd92289 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob -> org.hibernate.type.BasicTypeReference@1a8e44fe +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob_wrapper -> org.hibernate.type.BasicTypeReference@287317df +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Short -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration integer -> org.hibernate.type.BasicTypeReference@1987807b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration int -> org.hibernate.type.BasicTypeReference@1987807b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Integer -> org.hibernate.type.BasicTypeReference@1987807b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Long -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Float -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Double -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_integer -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigInteger -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_decimal -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigDecimal -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Character -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character_nchar -> org.hibernate.type.BasicTypeReference@2b464384 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration string -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.String -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nstring -> org.hibernate.type.BasicTypeReference@77f7352a +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration characters -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char[] -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [C -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-characters -> org.hibernate.type.BasicTypeReference@571db8b4 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration text -> org.hibernate.type.BasicTypeReference@65a2755e +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ntext -> org.hibernate.type.BasicTypeReference@2b3242a5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration clob -> org.hibernate.type.BasicTypeReference@11120583 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Clob -> org.hibernate.type.BasicTypeReference@11120583 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nclob -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.NClob -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob -> org.hibernate.type.BasicTypeReference@5d8e4fa8 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_char_array -> org.hibernate.type.BasicTypeReference@649009d6 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_character_array -> org.hibernate.type.BasicTypeReference@652f26da +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_character_array -> org.hibernate.type.BasicTypeReference@6796a873 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_char_array -> org.hibernate.type.BasicTypeReference@3acc3ee +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> org.hibernate.type.BasicTypeReference@1f293cb7 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> org.hibernate.type.BasicTypeReference@1f293cb7 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDateTime -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDateTime -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDate -> org.hibernate.type.BasicTypeReference@5790cbcb +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDate -> org.hibernate.type.BasicTypeReference@5790cbcb +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalTime -> org.hibernate.type.BasicTypeReference@32c6d164 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalTime -> org.hibernate.type.BasicTypeReference@32c6d164 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> org.hibernate.type.BasicTypeReference@645c9f0f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> org.hibernate.type.BasicTypeReference@645c9f0f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@999cd18 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeUtc -> org.hibernate.type.BasicTypeReference@df432ec +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithTimezone -> org.hibernate.type.BasicTypeReference@6144e499 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@26f204a4 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> org.hibernate.type.BasicTypeReference@28295554 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> org.hibernate.type.BasicTypeReference@28295554 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@4e671ef +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@42403dc6 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration date -> org.hibernate.type.BasicTypeReference@74a1d60e +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Date -> org.hibernate.type.BasicTypeReference@74a1d60e +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration time -> org.hibernate.type.BasicTypeReference@16c0be3b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Time -> org.hibernate.type.BasicTypeReference@16c0be3b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timestamp -> org.hibernate.type.BasicTypeReference@219edc05 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Timestamp -> org.hibernate.type.BasicTypeReference@219edc05 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Date -> org.hibernate.type.BasicTypeReference@219edc05 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar -> org.hibernate.type.BasicTypeReference@62f37bfd +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Calendar -> org.hibernate.type.BasicTypeReference@62f37bfd +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.GregorianCalendar -> org.hibernate.type.BasicTypeReference@62f37bfd +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_date -> org.hibernate.type.BasicTypeReference@1818d00b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_time -> org.hibernate.type.BasicTypeReference@b3a8455 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration instant -> org.hibernate.type.BasicTypeReference@5c930fc3 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Instant -> org.hibernate.type.BasicTypeReference@5c930fc3 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.UUID -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration pg-uuid -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-binary -> org.hibernate.type.BasicTypeReference@7b80af04 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-char -> org.hibernate.type.BasicTypeReference@2447940d +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration class -> org.hibernate.type.BasicTypeReference@60ee7a51 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Class -> org.hibernate.type.BasicTypeReference@60ee7a51 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration currency -> org.hibernate.type.BasicTypeReference@70e1aa20 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Currency -> org.hibernate.type.BasicTypeReference@70e1aa20 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Currency -> org.hibernate.type.BasicTypeReference@70e1aa20 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration locale -> org.hibernate.type.BasicTypeReference@e67d3b7 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Locale -> org.hibernate.type.BasicTypeReference@e67d3b7 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration serializable -> org.hibernate.type.BasicTypeReference@1618c98a +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.io.Serializable -> org.hibernate.type.BasicTypeReference@1618c98a +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timezone -> org.hibernate.type.BasicTypeReference@5b715ea +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.TimeZone -> org.hibernate.type.BasicTypeReference@5b715ea +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZoneOffset -> org.hibernate.type.BasicTypeReference@787a0fd6 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZoneOffset -> org.hibernate.type.BasicTypeReference@787a0fd6 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration url -> org.hibernate.type.BasicTypeReference@48b09105 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.net.URL -> org.hibernate.type.BasicTypeReference@48b09105 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration vector -> org.hibernate.type.BasicTypeReference@18b45500 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration row_version -> org.hibernate.type.BasicTypeReference@25110bb9 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration object -> org.hibernate.type.JavaObjectType@30eb55c9 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@30eb55c9 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration null -> org.hibernate.type.NullType@5badeda0 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_date -> org.hibernate.type.BasicTypeReference@56a9a7b5 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_time -> org.hibernate.type.BasicTypeReference@338270ea +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_timestamp -> org.hibernate.type.BasicTypeReference@7f64bd7 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar -> org.hibernate.type.BasicTypeReference@1c79d093 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_date -> org.hibernate.type.BasicTypeReference@746fd19b +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_time -> org.hibernate.type.BasicTypeReference@54caeadc +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_binary -> org.hibernate.type.BasicTypeReference@61d7bb61 +2025-10-23 17:38:10 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_serializable -> org.hibernate.type.BasicTypeReference@33f81280 +2025-10-23 17:38:10 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer +2025-10-23 17:38:10 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... +2025-10-23 17:38:11 [main] WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata +java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null + at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) + at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20) +2025-10-23 17:38:11 [main] ERROR o.s.o.j.LocalContainerEntityManagerFactoryBean - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) +2025-10-23 17:38:11 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) +2025-10-23 17:38:11 [main] INFO o.a.catalina.core.StandardService - Stopping service [Tomcat] +2025-10-23 17:38:11 [main] INFO o.s.b.a.l.ConditionEvaluationReportLogger - + +Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. +2025-10-23 17:38:11 [main] ERROR o.s.boot.SpringApplication - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) + at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) + ... 15 common frames omitted +Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:191) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentWithDefaults(JdbcEnvironmentInitiator.java:152) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:362) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) + ... 30 common frames omitted diff --git a/build/reports/problems/problems-report.html b/build/reports/problems/problems-report.html index 54d21ff..ab20623 100644 --- a/build/reports/problems/problems-report.html +++ b/build/reports/problems/problems-report.html @@ -650,7 +650,7 @@ code + .copy-button { diff --git a/design/backend/api/stt-service-api.yaml b/design/backend/api/stt-service-api.yaml index 0c95dda..d5c31dd 100644 --- a/design/backend/api/stt-service-api.yaml +++ b/design/backend/api/stt-service-api.yaml @@ -7,14 +7,12 @@ info: **핵심 기능:** - 음성 녹음 시작/중지 관리 - 실시간 음성-텍스트 변환 (스트리밍) - - 배치 음성-텍스트 변환 - - 화자 식별 및 관리 - Azure Speech Service 통합 **차별화 포인트:** - 기본 기능 (Hygiene Factor) - 경쟁사 대부분 제공 - 실시간 스트리밍 처리로 즉각적인 자막 제공 - - 화자 자동 식별 (90% 이상 정확도) + - **단순화**: 배치 처리 및 화자 식별 제거, 실시간 전용 기능 version: 1.0.0 contact: name: STT Service Team @@ -25,7 +23,7 @@ servers: description: Production Server - url: https://dev-api.example.com/stt/v1 description: Development Server - - url: http://localhost:8083/api/v1 + - url: http://localhost:8084/api/v1 description: Local Development Server tags: @@ -33,8 +31,6 @@ tags: description: 음성 녹음 관리 API - name: Transcription description: 음성-텍스트 변환 API - - name: Speaker - description: 화자 식별 및 관리 API paths: /recordings/prepare: @@ -50,7 +46,7 @@ paths: 2. DB에 녹음 정보 생성 3. Azure Speech 인식기 초기화 4. Blob Storage 저장 경로 생성 - 5. RecordingStarted 이벤트 발행 + 5. RecordingStarted 이벤트 발행 (Kafka) operationId: prepareRecording x-user-story: UFR-STT-010 x-controller: RecordingController @@ -243,15 +239,14 @@ paths: **처리 흐름:** 1. 음성 데이터 스트림 수신 2. Azure Speech Service 실시간 인식 - 3. 화자 식별 - 4. 신뢰도 검증 (70% threshold) - 5. DB에 세그먼트 저장 - 6. TranscriptSegmentReady 이벤트 발행 - 7. WebSocket으로 실시간 자막 전송 + 3. 신뢰도 검증 (70% threshold) + 4. DB에 세그먼트 저장 + 5. TranscriptSegmentReady 이벤트 발행 (Kafka) + 6. WebSocket으로 실시간 자막 전송 **성능:** - 실시간 인식 지연: < 1초 - - 처리 시간: 1-4초 + - 처리 시간: 1-3초 operationId: streamTranscription x-user-story: UFR-STT-020 x-controller: TranscriptController @@ -277,8 +272,6 @@ paths: transcriptId: "TRS-SEG-001" recordingId: "REC-20250123-001" text: "안녕하세요, 오늘 회의를 시작하겠습니다." - speakerId: "SPK-001" - speakerName: "김철수" timestamp: 1234567890 duration: 3.5 confidence: 0.92 @@ -290,94 +283,6 @@ paths: security: - BearerAuth: [] - /transcripts/batch: - post: - tags: - - Transcription - summary: 배치 음성-텍스트 변환 - description: | - 전체 오디오 파일을 배치로 변환 (비동기 처리) - - **처리 흐름:** - 1. 전체 오디오 파일 업로드 - 2. Azure Batch Transcription Job 생성 - 3. 비동기 처리 시작 - 4. Job ID 반환 (202 Accepted) - 5. 처리 완료 시 Callback으로 결과 수신 - - **처리 시간:** - - 파일 업로드: 1-2초 - - Azure 배치 처리: 5-30초 (파일 크기 따라) - - 총 처리 시간: 7-33초 - operationId: batchTranscription - x-user-story: UFR-STT-020 - x-controller: TranscriptController - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/BatchTranscriptionRequest' - responses: - '202': - description: 배치 작업 접수됨 - content: - application/json: - schema: - $ref: '#/components/schemas/BatchTranscriptionResponse' - example: - jobId: "JOB-20250123-001" - recordingId: "REC-20250123-001" - status: "PROCESSING" - estimatedCompletionTime: "2025-01-23T10:31:00Z" - callbackUrl: "https://api.example.com/stt/v1/transcripts/callback" - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' - security: - - BearerAuth: [] - - /transcripts/callback: - post: - tags: - - Transcription - summary: 배치 변환 완료 콜백 - description: | - Azure Speech Service로부터 배치 변환 완료 콜백 수신 - - **처리 흐름:** - 1. 배치 결과 수신 - 2. 세그먼트별 DB 저장 - 3. 전체 텍스트 병합 - 4. TranscriptionCompleted 이벤트 발행 - operationId: batchTranscriptionCallback - x-user-story: UFR-STT-020 - x-controller: TranscriptController - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BatchCallbackRequest' - responses: - '200': - description: 콜백 처리 성공 - content: - application/json: - schema: - $ref: '#/components/schemas/TranscriptionCompleteResponse' - example: - jobId: "JOB-20250123-001" - recordingId: "REC-20250123-001" - status: "COMPLETED" - segmentCount: 120 - totalDuration: 1800 - averageConfidence: 0.88 - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' /transcripts/{recordingId}: get: @@ -389,7 +294,7 @@ paths: **응답 데이터:** - 전체 텍스트 - - 화자별 세그먼트 목록 + - 세그먼트 목록 - 타임스탬프 정보 - 신뢰도 점수 operationId: getTranscription @@ -404,13 +309,6 @@ paths: schema: type: boolean default: false - - name: speakerId - in: query - description: 특정 화자의 발언만 필터링 - required: false - schema: - type: string - example: "SPK-001" responses: '200': description: 변환 텍스트 조회 성공 @@ -420,16 +318,13 @@ paths: $ref: '#/components/schemas/TranscriptionResponse' example: recordingId: "REC-20250123-001" - fullText: "김철수: 안녕하세요...\n이영희: 네, 안녕하세요..." + fullText: "안녕하세요, 오늘 회의를 시작하겠습니다..." segmentCount: 120 totalDuration: 1800 averageConfidence: 0.88 - speakerCount: 3 segments: - transcriptId: "TRS-SEG-001" text: "안녕하세요, 오늘 회의를 시작하겠습니다." - speakerId: "SPK-001" - speakerName: "김철수" timestamp: 0 duration: 3.5 confidence: 0.92 @@ -440,179 +335,6 @@ paths: security: - BearerAuth: [] - /speakers/identify: - post: - tags: - - Speaker - summary: 화자 식별 - description: | - 음성 데이터로부터 화자 식별 - - **처리 흐름:** - 1. Voice signature 생성 - 2. 기존 프로필과 매칭 - 3. 신규 화자 자동 등록 - 4. 화자 정보 반환 - - **정확도:** - - 화자 식별 정확도: > 90% - - 처리 시간: ~300ms - operationId: identifySpeaker - x-user-story: UFR-STT-010 - x-controller: SpeakerController - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifySpeakerRequest' - example: - recordingId: "REC-20250123-001" - audioFrame: "base64_encoded_audio_frame" - timestamp: 1234567890 - responses: - '200': - description: 화자 식별 성공 - content: - application/json: - schema: - $ref: '#/components/schemas/SpeakerIdentificationResponse' - example: - speakerId: "SPK-001" - speakerName: "김철수" - confidence: 0.95 - isNewSpeaker: false - profileId: "PROFILE-12345" - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' - security: - - BearerAuth: [] - - /speakers/{speakerId}: - get: - tags: - - Speaker - summary: 화자 정보 조회 - description: 특정 화자의 상세 정보 조회 - operationId: getSpeaker - x-user-story: UFR-STT-010 - x-controller: SpeakerController - parameters: - - name: speakerId - in: path - description: 화자 ID - required: true - schema: - type: string - example: "SPK-001" - responses: - '200': - description: 화자 정보 조회 성공 - content: - application/json: - schema: - $ref: '#/components/schemas/SpeakerDetailResponse' - example: - speakerId: "SPK-001" - speakerName: "김철수" - profileId: "PROFILE-12345" - totalSegments: 45 - totalDuration: 450 - averageConfidence: 0.92 - firstAppeared: "2025-01-23T10:30:15Z" - lastAppeared: "2025-01-23T11:00:00Z" - '404': - $ref: '#/components/responses/NotFound' - '500': - $ref: '#/components/responses/InternalServerError' - security: - - BearerAuth: [] - - put: - tags: - - Speaker - summary: 화자 정보 업데이트 - description: 화자 이름 등 정보 수정 - operationId: updateSpeaker - x-user-story: UFR-STT-010 - x-controller: SpeakerController - parameters: - - name: speakerId - in: path - description: 화자 ID - required: true - schema: - type: string - example: "SPK-001" - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateSpeakerRequest' - example: - speakerName: "김철수 팀장" - userId: "USER-123" - responses: - '200': - description: 화자 정보 업데이트 성공 - content: - application/json: - schema: - $ref: '#/components/schemas/SpeakerDetailResponse' - '404': - $ref: '#/components/responses/NotFound' - '500': - $ref: '#/components/responses/InternalServerError' - security: - - BearerAuth: [] - - /recordings/{recordingId}/speakers: - get: - tags: - - Speaker - summary: 녹음의 화자 목록 조회 - description: 특정 녹음에 참여한 모든 화자 목록 조회 - operationId: getRecordingSpeakers - x-user-story: UFR-STT-010 - x-controller: SpeakerController - parameters: - - $ref: '#/components/parameters/RecordingIdParam' - responses: - '200': - description: 화자 목록 조회 성공 - content: - application/json: - schema: - $ref: '#/components/schemas/SpeakerListResponse' - example: - recordingId: "REC-20250123-001" - speakerCount: 3 - speakers: - - speakerId: "SPK-001" - speakerName: "김철수" - segmentCount: 45 - totalDuration: 450 - speakingRatio: 0.45 - - speakerId: "SPK-002" - speakerName: "이영희" - segmentCount: 38 - totalDuration: 380 - speakingRatio: 0.38 - - speakerId: "SPK-003" - speakerName: "박민수" - segmentCount: 17 - totalDuration: 170 - speakingRatio: 0.17 - '404': - $ref: '#/components/responses/NotFound' - '500': - $ref: '#/components/responses/InternalServerError' - security: - - BearerAuth: [] - components: securitySchemes: BearerAuth: @@ -657,7 +379,7 @@ components: example: "ko-KR" attendeeCount: type: integer - description: 참석자 수 (화자 식별 최적화용) + description: 참석자 수 minimum: 1 maximum: 50 example: 5 @@ -809,10 +531,6 @@ components: type: integer description: 녹음 시간 (초) example: 300 - speakerCount: - type: integer - description: 화자 수 - example: 3 segmentCount: type: integer description: 세그먼트 수 @@ -866,14 +584,6 @@ components: type: string description: 변환된 텍스트 example: "안녕하세요, 오늘 회의를 시작하겠습니다." - speakerId: - type: string - description: 화자 ID - example: "SPK-001" - speakerName: - type: string - description: 화자 이름 - example: "김철수" timestamp: type: integer description: 타임스탬프 (ms) @@ -895,89 +605,6 @@ components: description: 낮은 신뢰도 경고 플래그 (< 60%) example: false - BatchTranscriptionRequest: - type: object - required: - - recordingId - - audioFile - properties: - recordingId: - type: string - description: 녹음 ID - example: "REC-20250123-001" - audioFile: - type: string - format: binary - description: 오디오 파일 (WAV, MP3 등) - language: - type: string - description: 음성 인식 언어 - default: "ko-KR" - example: "ko-KR" - callbackUrl: - type: string - format: uri - description: 처리 완료 콜백 URL - example: "https://api.example.com/stt/v1/transcripts/callback" - - BatchTranscriptionResponse: - type: object - properties: - jobId: - type: string - description: 배치 작업 ID - example: "JOB-20250123-001" - recordingId: - type: string - description: 녹음 ID - example: "REC-20250123-001" - status: - type: string - description: 작업 상태 - enum: - - QUEUED - - PROCESSING - - COMPLETED - - FAILED - example: "PROCESSING" - estimatedCompletionTime: - type: string - format: date-time - description: 예상 완료 시간 - example: "2025-01-23T10:31:00Z" - callbackUrl: - type: string - format: uri - description: 콜백 URL - example: "https://api.example.com/stt/v1/transcripts/callback" - - BatchCallbackRequest: - type: object - required: - - jobId - - status - - segments - properties: - jobId: - type: string - description: 배치 작업 ID - example: "JOB-20250123-001" - status: - type: string - description: 작업 상태 - enum: - - COMPLETED - - FAILED - example: "COMPLETED" - segments: - type: array - description: 변환 세그먼트 목록 - items: - $ref: '#/components/schemas/TranscriptionSegment' - error: - type: string - description: 오류 메시지 (실패 시) - example: "Audio file format not supported" TranscriptionSegment: type: object @@ -986,10 +613,6 @@ components: type: string description: 변환된 텍스트 example: "안녕하세요, 오늘 회의를 시작하겠습니다." - speakerId: - type: string - description: 화자 ID - example: "SPK-001" timestamp: type: integer description: 시작 타임스탬프 (ms) @@ -1061,10 +684,6 @@ components: format: float description: 평균 신뢰도 점수 example: 0.88 - speakerCount: - type: integer - description: 화자 수 - example: 3 segments: type: array description: 세그먼트 목록 @@ -1082,14 +701,6 @@ components: type: string description: 변환된 텍스트 example: "안녕하세요, 오늘 회의를 시작하겠습니다." - speakerId: - type: string - description: 화자 ID - example: "SPK-001" - speakerName: - type: string - description: 화자 이름 - example: "김철수" timestamp: type: integer description: 타임스탬프 (ms) @@ -1105,151 +716,6 @@ components: description: 신뢰도 점수 example: 0.92 - IdentifySpeakerRequest: - type: object - required: - - recordingId - - audioFrame - - timestamp - properties: - recordingId: - type: string - description: 녹음 ID - example: "REC-20250123-001" - audioFrame: - type: string - format: byte - description: Base64 인코딩된 오디오 프레임 - example: "UklGRiQAAABXQVZFZm10IBAAAAABA..." - timestamp: - type: integer - description: 타임스탬프 (ms) - example: 1234567890 - - SpeakerIdentificationResponse: - type: object - properties: - speakerId: - type: string - description: 화자 ID - example: "SPK-001" - speakerName: - type: string - description: 화자 이름 - example: "김철수" - confidence: - type: number - format: float - description: 식별 신뢰도 (0-1) - minimum: 0 - maximum: 1 - example: 0.95 - isNewSpeaker: - type: boolean - description: 신규 화자 여부 - example: false - profileId: - type: string - description: Azure Speaker Profile ID - example: "PROFILE-12345" - - SpeakerDetailResponse: - type: object - properties: - speakerId: - type: string - description: 화자 ID - example: "SPK-001" - speakerName: - type: string - description: 화자 이름 - example: "김철수" - profileId: - type: string - description: Azure Speaker Profile ID - example: "PROFILE-12345" - userId: - type: string - description: 연결된 사용자 ID - example: "USER-123" - totalSegments: - type: integer - description: 총 발언 세그먼트 수 - example: 45 - totalDuration: - type: integer - description: 총 발언 시간 (초) - example: 450 - averageConfidence: - type: number - format: float - description: 평균 식별 신뢰도 - example: 0.92 - firstAppeared: - type: string - format: date-time - description: 최초 등장 시간 - example: "2025-01-23T10:30:15Z" - lastAppeared: - type: string - format: date-time - description: 최근 등장 시간 - example: "2025-01-23T11:00:00Z" - - UpdateSpeakerRequest: - type: object - properties: - speakerName: - type: string - description: 화자 이름 - example: "김철수 팀장" - userId: - type: string - description: 연결할 사용자 ID - example: "USER-123" - - SpeakerListResponse: - type: object - properties: - recordingId: - type: string - description: 녹음 ID - example: "REC-20250123-001" - speakerCount: - type: integer - description: 화자 수 - example: 3 - speakers: - type: array - description: 화자 목록 - items: - $ref: '#/components/schemas/SpeakerSummary' - - SpeakerSummary: - type: object - properties: - speakerId: - type: string - description: 화자 ID - example: "SPK-001" - speakerName: - type: string - description: 화자 이름 - example: "김철수" - segmentCount: - type: integer - description: 발언 세그먼트 수 - example: 45 - totalDuration: - type: integer - description: 총 발언 시간 (초) - example: 450 - speakingRatio: - type: number - format: float - description: 발언 비율 (0-1) - example: 0.45 - ErrorResponse: type: object properties: diff --git a/design/backend/sequence/inner/stt-녹음시작및인식.puml b/design/backend/sequence/inner/stt-녹음시작및인식.puml index 32f482a..ec12ec1 100644 --- a/design/backend/sequence/inner/stt-녹음시작및인식.puml +++ b/design/backend/sequence/inner/stt-녹음시작및인식.puml @@ -1,14 +1,13 @@ @startuml !theme mono -title STT Service - 음성 녹음 시작 및 화자 인식 (통합) +title STT Service - 음성 녹음 시작 및 실시간 인식 participant "Frontend<>" as Frontend participant "API Gateway<>" as Gateway participant "RecordingController" as Controller participant "RecordingService" as Service participant "AudioStreamManager" as StreamManager -participant "SpeakerIdentifier" as Speaker participant "RecordingRepository" as Repository participant "AzureSpeechClient" as AzureClient database "STT DB" as DB @@ -51,7 +50,6 @@ note right - 언어: ko-KR - Format: PCM 16kHz - 샘플레이트: 16kHz - - 화자 식별 활성화 - 실시간 스트리밍 모드 - Continuous recognition end note @@ -108,32 +106,12 @@ deactivate AzureClient StreamManager --> Service: recognized text deactivate StreamManager -== 화자 식별 == - -Service -> Speaker: identifySpeaker(audioFrame) -activate Speaker - -Speaker -> AzureClient: analyzeSpeakerProfile()\n(Speaker Recognition API) -activate AzureClient -note right - 화자 식별: - - Voice signature 생성 - - 기존 프로필과 매칭 - - 신규 화자 자동 등록 -end note - -AzureClient --> Speaker: speakerId -deactivate AzureClient - -Speaker --> Service: speaker info -deactivate Speaker - -== 화자별 세그먼트 저장 == +== 세그먼트 저장 == Service -> Repository: saveSttSegment(segment) activate Repository -Repository -> DB: STT 세그먼트 저장\n(세션ID, 텍스트, 화자ID, 타임스탬프, 신뢰도) +Repository -> DB: STT 세그먼트 저장\n(세션ID, 텍스트, 타임스탬프, 신뢰도) activate DB DB --> Repository: segment saved deactivate DB @@ -141,24 +119,13 @@ deactivate DB Repository --> Service: saved deactivate Repository -Service -> Repository: updateSpeakerInfo(recordingId, speakerId) -activate Repository - -Repository -> DB: 화자 정보 저장/업데이트\n(녹음ID, 화자ID, 세그먼트수) -activate DB -DB --> Repository: 업데이트 완료 -deactivate DB - -Repository --> Service: 완료 -deactivate Repository - -Service --> Controller: streaming response\n{text, speaker, timestamp, confidence} +Service --> Controller: streaming response\n{text, timestamp, confidence} deactivate Service Controller --> Gateway: WebSocket message deactivate Controller -Gateway --> Frontend: 실시간 자막 전송\n{text, speaker, timestamp} +Gateway --> Frontend: 실시간 자막 전송\n{text, timestamp} deactivate Gateway note over Frontend, EventHub @@ -166,12 +133,10 @@ note over Frontend, EventHub - DB 녹음 생성: ~100ms - Azure 인식기 초기화: ~500ms - Blob 경로 생성: ~200ms -- 화자 식별: ~300ms - 실시간 인식 지연: < 1초 -- 총 초기화 시간: ~1.1초 +- 총 초기화 시간: ~0.8초 정확도: -- 화자 식별 정확도: > 90% - 음성 인식 정확도: 60-95% end note diff --git a/design/backend/sequence/inner/stt-텍스트변환통합.puml b/design/backend/sequence/inner/stt-텍스트변환통합.puml index 9ce6586..ec0f538 100644 --- a/design/backend/sequence/inner/stt-텍스트변환통합.puml +++ b/design/backend/sequence/inner/stt-텍스트변환통합.puml @@ -1,7 +1,7 @@ @startuml !theme mono -title STT Service - 음성-텍스트 변환 (실시간/배치 통합) +title STT Service - 음성-텍스트 변환 (실시간 전용) participant "Frontend<>" as Frontend participant "API Gateway<>" as Gateway @@ -15,7 +15,7 @@ database "STT DB" as DB database "Azure Blob Storage<>" as BlobStorage queue "Azure Event Hubs<>" as EventHub -== 음성 데이터 스트리밍 수신 (실시간 모드) == +== 음성 데이터 스트리밍 수신 == Frontend -> Gateway: POST /api/transcripts/stream\n(audioData, recordingId, timestamp) activate Gateway @@ -26,9 +26,8 @@ activate Controller Controller -> Service: processAudioStream(audioData, recordingId) activate Service -alt 실시간 변환 모드 - Service -> Engine: streamingTranscribe(audioData) - activate Engine +Service -> Engine: streamingTranscribe(audioData) +activate Engine Engine -> AzureClient: recognizeAsync(audioData) activate AzureClient @@ -38,7 +37,6 @@ alt 실시간 변환 모드 Azure Speech 설정: - Mode: Continuous - 언어: ko-KR - - 화자 식별 활성화 - 타임스탬프 자동 기록 - 신뢰도 점수 계산 - Profanity filter @@ -49,7 +47,7 @@ alt 실시간 변환 모드 BlobStorage --> AzureClient: 저장 완료 deactivate BlobStorage - AzureClient --> Engine: RecognitionResult\n(text, speakerId, confidence, timestamp, duration) + AzureClient --> Engine: RecognitionResult\n(text, confidence, timestamp, duration) deactivate AzureClient == 정확도 검증 및 처리 == @@ -71,7 +69,7 @@ alt 실시간 변환 모드 Service -> TranscriptRepo: createTranscript(recordingId, segment) activate TranscriptRepo - TranscriptRepo -> DB: 변환 결과 저장\n(텍스트ID, 녹음ID, 화자ID, 텍스트, 신뢰도, 타임스탬프, 경고플래그) + TranscriptRepo -> DB: 변환 결과 저장\n(텍스트ID, 녹음ID, 텍스트, 신뢰도, 타임스탬프, 경고플래그) activate DB DB --> TranscriptRepo: transcriptId 반환 deactivate DB @@ -79,19 +77,6 @@ alt 실시간 변환 모드 TranscriptRepo --> Service: TranscriptEntity 반환 deactivate TranscriptRepo - == 화자 정보 업데이트 == - - Service -> RecordingRepo: updateSpeakerInfo(recordingId, speakerId) - activate RecordingRepo - - RecordingRepo -> DB: 화자 정보 저장/업데이트\n(녹음ID, 화자ID, 세그먼트수) - activate DB - DB --> RecordingRepo: 업데이트 완료 - deactivate DB - - RecordingRepo --> Service: 완료 - deactivate RecordingRepo - == 이벤트 발행 == Service -> EventHub: TranscriptSegmentReady 이벤트 발행 @@ -102,7 +87,6 @@ alt 실시간 변환 모드 - recordingId - meetingId - text - - speakerId - timestamp - confidence end note @@ -112,128 +96,18 @@ alt 실시간 변환 모드 Service --> Controller: TranscriptResponse\n(transcriptId, text, confidence, warningFlag) deactivate Service - Controller --> Gateway: 200 OK\n(transcriptId, text, speakerId, timestamp, confidence) + Controller --> Gateway: 200 OK\n(transcriptId, text, timestamp, confidence) deactivate Controller Gateway --> Frontend: 실시간 자막 응답 deactivate Gateway -else 배치 변환 모드 - Gateway -> Controller: POST /api/v1/stt/transcribe\n{sessionId, audioFile} - activate Controller - - Controller -> Service: transcribeAudio(sessionId, audioFile) - activate Service - - Service -> RecordingRepo: findSessionById(sessionId) - activate RecordingRepo - RecordingRepo -> DB: STT 세션 조회\n(세션ID 기준) - DB --> RecordingRepo: session data - RecordingRepo --> Service: RecordingEntity - deactivate RecordingRepo - - Service -> Engine: batchTranscribe(audioFile) - activate Engine - - Engine -> AzureClient: batchTranscriptionAsync(audioUrl) - activate AzureClient - note right - 배치 처리: - - 전체 파일 업로드 - - 백그라운드 처리 - - Callback URL 제공 - - 화자별 그룹화 - - 문장 경계 보정 - end note - - AzureClient --> Engine: transcription job ID - deactivate AzureClient - - Engine --> Service: job submitted - deactivate Engine - - Service -> RecordingRepo: updateSessionStatus(sessionId, "PROCESSING") - activate RecordingRepo - RecordingRepo -> DB: 세션 상태 업데이트\n(상태='처리중') - DB --> RecordingRepo: updated - RecordingRepo --> Service: updated - deactivate RecordingRepo - - Service --> Controller: 202 Accepted\n{jobId, status} - deactivate Service - - Controller --> Gateway: 202 Accepted - deactivate Controller - - == 배치 처리 완료 (Callback) == - - AzureClient -> Controller: POST /api/v1/stt/callback\n{jobId, segments} - activate Controller - - Controller -> Service: processBatchResult(jobId, segments) - activate Service - - loop 각 세그먼트 처리 - Service -> TranscriptRepo: createTranscript(recordingId, segment) - activate TranscriptRepo - TranscriptRepo -> DB: 변환 결과 저장 - DB --> TranscriptRepo: saved - TranscriptRepo --> Service: saved - deactivate TranscriptRepo - end - - == 전체 텍스트 통합 == - - Service -> TranscriptRepo: aggregateTranscription(sessionId) - activate TranscriptRepo - TranscriptRepo -> DB: 세그먼트 목록 조회\n(세션ID 기준, 타임스탬프 순 정렬) - DB --> TranscriptRepo: ordered segments - TranscriptRepo --> Service: segments - deactivate TranscriptRepo - - Service -> Service: mergeSegments(segments) - note right - 세그먼트 병합: - - 화자별 그룹화 - - 시간 순서 정렬 - - 문장 경계 보정 - end note - - Service -> RecordingRepo: saveTranscription(fullText) - activate RecordingRepo - RecordingRepo -> DB: 전체 텍스트 저장 및 상태 업데이트\n(전체텍스트, 상태='완료') - DB --> RecordingRepo: saved - RecordingRepo --> Service: updated session - deactivate RecordingRepo - - Service -> EventHub: TranscriptionCompletedEvent 발행 - note right - Event: - - sessionId - - meetingId - - fullText - - completedAt - end note - - Service --> Controller: TranscriptionResponse\n{sessionId, text, segments} - deactivate Service - - Controller --> Gateway: 200 OK\n{transcription, metadata} - deactivate Controller -end - note over Frontend, EventHub -**실시간 모드 처리 시간:** +**처리 시간:** - Azure STT 처리: 1-3초 - DB 저장: ~100ms - Event 발행: ~50ms -- 총 처리 시간: 1-4초 - -**배치 모드 처리 시간:** -- 파일 업로드: ~1-2초 -- Azure 배치 처리: 5-30초 (파일 크기에 따라) -- DB 저장: ~500ms -- 총 처리 시간: 7-33초 +- 총 처리 시간: 1-3초 **정확도 경고 기준:** - < 60%: 수동 수정 권장 (경고 플래그) diff --git a/logs/ai.log b/logs/ai.log index c9db9ae..d19237f 100644 --- a/logs/ai.log +++ b/logs/ai.log @@ -1438,3 +1438,282 @@ Caused by: io.lettuce.core.RedisCommandExecutionException: NOAUTH HELLO must be 2025-10-23 16:37:29 [SpringApplicationShutdownHook] DEBUG o.h.type.spi.TypeConfiguration$Scope - Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@1d9c4491] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@20505460] 2025-10-23 16:37:29 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated... 2025-10-23 16:37:29 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed. +2025-10-23 17:10:40 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 43872 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero) +2025-10-23 17:10:40 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8 +2025-10-23 17:10:40 [main] INFO com.unicorn.hgzero.ai.AiApplication - No active profile set, falling back to 1 default profile: "default" +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces. +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2025-10-23 17:10:40 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces. +2025-10-23 17:10:41 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8084 (http) +2025-10-23 17:10:41 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat] +2025-10-23 17:10:41 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24] +2025-10-23 17:10:41 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext +2025-10-23 17:10:41 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 776 ms +2025-10-23 17:10:41 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] +2025-10-23 17:10:41 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final +2025-10-23 17:10:41 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Boolean -> org.hibernate.type.BasicTypeReference@3e2d65e1 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration numeric_boolean -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.NumericBooleanConverter -> org.hibernate.type.BasicTypeReference@1174676f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration true_false -> org.hibernate.type.BasicTypeReference@71f8ce0e +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.TrueFalseConverter -> org.hibernate.type.BasicTypeReference@71f8ce0e +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration yes_no -> org.hibernate.type.BasicTypeReference@4fd92289 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.YesNoConverter -> org.hibernate.type.BasicTypeReference@4fd92289 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@1a8e44fe +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@1a8e44fe +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Byte -> org.hibernate.type.BasicTypeReference@1a8e44fe +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary -> org.hibernate.type.BasicTypeReference@287317df +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte[] -> org.hibernate.type.BasicTypeReference@287317df +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [B -> org.hibernate.type.BasicTypeReference@287317df +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary_wrapper -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-binary -> org.hibernate.type.BasicTypeReference@1fcc3461 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration image -> org.hibernate.type.BasicTypeReference@1987807b +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration blob -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Blob -> org.hibernate.type.BasicTypeReference@71469e01 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob -> org.hibernate.type.BasicTypeReference@41bbb219 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob_wrapper -> org.hibernate.type.BasicTypeReference@3f2ae973 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Short -> org.hibernate.type.BasicTypeReference@1a8b22b5 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration integer -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration int -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Integer -> org.hibernate.type.BasicTypeReference@5f781173 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Long -> org.hibernate.type.BasicTypeReference@43cf5bff +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@2b464384 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@2b464384 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Float -> org.hibernate.type.BasicTypeReference@2b464384 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Double -> org.hibernate.type.BasicTypeReference@681b42d3 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_integer -> org.hibernate.type.BasicTypeReference@77f7352a +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigInteger -> org.hibernate.type.BasicTypeReference@77f7352a +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_decimal -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigDecimal -> org.hibernate.type.BasicTypeReference@4ede8888 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character -> org.hibernate.type.BasicTypeReference@571db8b4 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char -> org.hibernate.type.BasicTypeReference@571db8b4 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Character -> org.hibernate.type.BasicTypeReference@571db8b4 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character_nchar -> org.hibernate.type.BasicTypeReference@65a2755e +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration string -> org.hibernate.type.BasicTypeReference@2b3242a5 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.String -> org.hibernate.type.BasicTypeReference@2b3242a5 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nstring -> org.hibernate.type.BasicTypeReference@11120583 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration characters -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char[] -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [C -> org.hibernate.type.BasicTypeReference@2bf0c70d +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-characters -> org.hibernate.type.BasicTypeReference@5d8e4fa8 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration text -> org.hibernate.type.BasicTypeReference@649009d6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ntext -> org.hibernate.type.BasicTypeReference@652f26da +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration clob -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Clob -> org.hibernate.type.BasicTypeReference@484a5ddd +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nclob -> org.hibernate.type.BasicTypeReference@6796a873 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.NClob -> org.hibernate.type.BasicTypeReference@6796a873 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob -> org.hibernate.type.BasicTypeReference@3acc3ee +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_char_array -> org.hibernate.type.BasicTypeReference@1f293cb7 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_character_array -> org.hibernate.type.BasicTypeReference@5972e3a +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob -> org.hibernate.type.BasicTypeReference@5790cbcb +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_character_array -> org.hibernate.type.BasicTypeReference@32c6d164 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_char_array -> org.hibernate.type.BasicTypeReference@645c9f0f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> org.hibernate.type.BasicTypeReference@58068b40 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDateTime -> org.hibernate.type.BasicTypeReference@999cd18 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDateTime -> org.hibernate.type.BasicTypeReference@999cd18 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDate -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDate -> org.hibernate.type.BasicTypeReference@dd060be +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalTime -> org.hibernate.type.BasicTypeReference@df432ec +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalTime -> org.hibernate.type.BasicTypeReference@df432ec +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> org.hibernate.type.BasicTypeReference@6144e499 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> org.hibernate.type.BasicTypeReference@6144e499 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@26f204a4 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@28295554 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> org.hibernate.type.BasicTypeReference@4e671ef +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> org.hibernate.type.BasicTypeReference@4e671ef +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeUtc -> org.hibernate.type.BasicTypeReference@42403dc6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithTimezone -> org.hibernate.type.BasicTypeReference@74a1d60e +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@16c0be3b +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> org.hibernate.type.BasicTypeReference@219edc05 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> org.hibernate.type.BasicTypeReference@219edc05 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@62f37bfd +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@1818d00b +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration date -> org.hibernate.type.BasicTypeReference@b3a8455 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Date -> org.hibernate.type.BasicTypeReference@b3a8455 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration time -> org.hibernate.type.BasicTypeReference@5c930fc3 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Time -> org.hibernate.type.BasicTypeReference@5c930fc3 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timestamp -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Timestamp -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Date -> org.hibernate.type.BasicTypeReference@25c6ab3f +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar -> org.hibernate.type.BasicTypeReference@7b80af04 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Calendar -> org.hibernate.type.BasicTypeReference@7b80af04 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.GregorianCalendar -> org.hibernate.type.BasicTypeReference@7b80af04 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_date -> org.hibernate.type.BasicTypeReference@2447940d +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_time -> org.hibernate.type.BasicTypeReference@60ee7a51 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration instant -> org.hibernate.type.BasicTypeReference@70e1aa20 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Instant -> org.hibernate.type.BasicTypeReference@70e1aa20 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid -> org.hibernate.type.BasicTypeReference@e67d3b7 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.UUID -> org.hibernate.type.BasicTypeReference@e67d3b7 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration pg-uuid -> org.hibernate.type.BasicTypeReference@e67d3b7 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-binary -> org.hibernate.type.BasicTypeReference@1618c98a +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-char -> org.hibernate.type.BasicTypeReference@5b715ea +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration class -> org.hibernate.type.BasicTypeReference@787a0fd6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Class -> org.hibernate.type.BasicTypeReference@787a0fd6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration currency -> org.hibernate.type.BasicTypeReference@48b09105 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Currency -> org.hibernate.type.BasicTypeReference@48b09105 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Currency -> org.hibernate.type.BasicTypeReference@48b09105 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration locale -> org.hibernate.type.BasicTypeReference@18b45500 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Locale -> org.hibernate.type.BasicTypeReference@18b45500 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration serializable -> org.hibernate.type.BasicTypeReference@25110bb9 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.io.Serializable -> org.hibernate.type.BasicTypeReference@25110bb9 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timezone -> org.hibernate.type.BasicTypeReference@dbda472 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.TimeZone -> org.hibernate.type.BasicTypeReference@dbda472 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZoneOffset -> org.hibernate.type.BasicTypeReference@41492479 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZoneOffset -> org.hibernate.type.BasicTypeReference@41492479 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration url -> org.hibernate.type.BasicTypeReference@7bef7505 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.net.URL -> org.hibernate.type.BasicTypeReference@7bef7505 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration vector -> org.hibernate.type.BasicTypeReference@568ef502 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration row_version -> org.hibernate.type.BasicTypeReference@36f05595 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration object -> org.hibernate.type.JavaObjectType@3c46e6f6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@3c46e6f6 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration null -> org.hibernate.type.NullType@1c79d093 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_date -> org.hibernate.type.BasicTypeReference@746fd19b +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_time -> org.hibernate.type.BasicTypeReference@61d7bb61 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_timestamp -> org.hibernate.type.BasicTypeReference@33f81280 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar -> org.hibernate.type.BasicTypeReference@3991fe6d +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_date -> org.hibernate.type.BasicTypeReference@3a0e7f89 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_time -> org.hibernate.type.BasicTypeReference@665ed71a +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_binary -> org.hibernate.type.BasicTypeReference@15c1b543 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_serializable -> org.hibernate.type.BasicTypeReference@23954300 +2025-10-23 17:10:41 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer +2025-10-23 17:10:41 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... +2025-10-23 17:10:41 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@5f5c0eda +2025-10-23 17:10:41 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. +2025-10-23 17:10:41 [main] DEBUG o.h.t.d.sql.spi.DdlTypeRegistry - addDescriptor(2003, org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl@31b7112d) replaced previous registration(org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl@47fc9ce) +2025-10-23 17:10:41 [main] DEBUG o.h.t.d.sql.spi.DdlTypeRegistry - addDescriptor(6, org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType@1b5d1d9) replaced previous registration(org.hibernate.type.descriptor.sql.internal.DdlTypeImpl@703a2bc9) +2025-10-23 17:10:41 [main] DEBUG o.h.t.d.jdbc.spi.JdbcTypeRegistry - addDescriptor(2004, BlobTypeDescriptor(BLOB_BINDING)) replaced previous registration(BlobTypeDescriptor(DEFAULT)) +2025-10-23 17:10:41 [main] DEBUG o.h.t.d.jdbc.spi.JdbcTypeRegistry - addDescriptor(2005, ClobTypeDescriptor(CLOB_BINDING)) replaced previous registration(ClobTypeDescriptor(DEFAULT)) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration JAVA_OBJECT -> org.hibernate.type.JavaObjectType@e460ca1 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@e460ca1 +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Type registration key [java.lang.Object] overrode previous entry : `org.hibernate.type.JavaObjectType@3c46e6f6` +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.DurationType -> basicType@1(java.time.Duration,3015) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> basicType@1(java.time.Duration,3015) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> basicType@1(java.time.Duration,3015) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.OffsetDateTimeType -> basicType@2(java.time.OffsetDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> basicType@2(java.time.OffsetDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> basicType@2(java.time.OffsetDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.ZonedDateTimeType -> basicType@3(java.time.ZonedDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> basicType@3(java.time.ZonedDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> basicType@3(java.time.ZonedDateTime,3003) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.OffsetTimeType -> basicType@4(java.time.OffsetTime,3007) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> basicType@4(java.time.OffsetTime,3007) +2025-10-23 17:10:41 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> basicType@4(java.time.OffsetTime,3007) +2025-10-23 17:10:41 [main] DEBUG o.h.type.spi.TypeConfiguration$Scope - Scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration@268e30d4] to MetadataBuildingContext [org.hibernate.boot.internal.MetadataBuildingContextRootImpl@7c50709a] +2025-10-23 17:10:41 [main] INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) +2025-10-23 17:10:41 [main] DEBUG o.h.type.spi.TypeConfiguration$Scope - Scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration@268e30d4] to SessionFactoryImplementor [org.hibernate.internal.SessionFactoryImpl@263f6e96] +2025-10-23 17:10:41 [main] TRACE o.h.type.spi.TypeConfiguration$Scope - Handling #sessionFactoryCreated from [org.hibernate.internal.SessionFactoryImpl@263f6e96] for TypeConfiguration +2025-10-23 17:10:41 [main] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' +2025-10-23 17:10:41 [main] WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning +2025-10-23 17:10:42 [main] ERROR i.n.r.d.DnsServerAddressStreamProviders - Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library +2025-10-23 17:10:42 [main] WARN o.s.b.a.s.s.UserDetailsServiceAutoConfiguration - + +Using generated security password: 4d9e182a-5838-4fd3-8e57-70219ebe9076 + +This generated password is for development use only. Your security configuration must be updated before running your application in production. + +2025-10-23 17:10:42 [main] INFO o.s.s.c.a.a.c.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer - Global AuthenticationManager configured with UserDetailsService bean with name inMemoryUserDetailsManager +2025-10-23 17:10:42 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 3 endpoints beneath base path '/actuator' +2025-10-23 17:10:42 [main] INFO o.s.s.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@23d1090, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@46c6541f, org.springframework.security.web.context.SecurityContextHolderFilter@67744663, org.springframework.security.web.header.HeaderWriterFilter@1a2bcce1, org.springframework.web.filter.CorsFilter@aba3735, org.springframework.security.web.csrf.CsrfFilter@417c9b17, org.springframework.security.web.authentication.logout.LogoutFilter@75b598a5, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@401b7109, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@24a024c8, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@16bba8ae, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@7f36b021, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@387cd426, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6295cc30, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7c689379, org.springframework.security.web.access.ExceptionTranslationFilter@ae5eeee, org.springframework.security.web.access.intercept.AuthorizationFilter@431bf770] +2025-10-23 17:10:42 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8084 (http) with context path '/' +2025-10-23 17:10:42 [main] INFO com.unicorn.hgzero.ai.AiApplication - Started AiApplication in 2.293 seconds (process running for 2.491) +2025-10-23 17:10:42 [RMI TCP Connection(1)-127.0.0.1] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet' +2025-10-23 17:10:42 [RMI TCP Connection(1)-127.0.0.1] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet' +2025-10-23 17:10:42 [RMI TCP Connection(1)-127.0.0.1] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 1 ms +2025-10-23 17:10:42 [boundedElastic-1] WARN o.s.b.a.d.r.RedisReactiveHealthIndicator - Redis health check failed +org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1847) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1778) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1580) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.lambda$getConnection$0(LettuceConnectionFactory.java:1560) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.doInLock(LettuceConnectionFactory.java:1521) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1557) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedReactiveConnection(LettuceConnectionFactory.java:1268) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:1143) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:119) + at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:67) + at reactor.core.publisher.FluxSubscribeOnCallable$CallableSubscribeOnSubscription.run(FluxSubscribeOnCallable.java:228) + at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) + at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) + at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1575) +Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 20.249.177.114/:6379 + at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) + at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) + at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:350) + at io.lettuce.core.RedisClient.connect(RedisClient.java:215) + at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:112) + at java.base/java.util.Optional.orElseGet(Optional.java:364) + at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:112) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1776) + ... 16 common frames omitted +Caused by: io.lettuce.core.RedisCommandExecutionException: NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO AUTH option can be used to authenticate the client and select the RESP protocol version at the same time + at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:147) + at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:116) + at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:120) + at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111) + at io.lettuce.core.protocol.CommandWrapper.complete(CommandWrapper.java:63) + at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:745) + at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:680) + at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:597) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) + at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) + at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) + at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) + at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) + at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) + at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) + at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) + at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) + at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994) + at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) + at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) + ... 1 common frames omitted +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.security.web.FilterChainProxy - Securing GET /swagger-ui.html +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.s.w.s.HttpSessionRequestCache - Saved request http://localhost:8084/swagger-ui.html?continue to session +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@49c72fb7, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]] +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@7d91e9c9 +2025-10-23 17:11:28 [http-nio-8084-exec-1] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login +2025-10-23 17:11:28 [http-nio-8084-exec-2] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login +2025-10-23 17:11:28 [http-nio-8084-exec-3] DEBUG o.s.security.web.FilterChainProxy - Securing GET /favicon.ico +2025-10-23 17:11:28 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext +2025-10-23 17:11:28 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@49c72fb7, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]] +2025-10-23 17:11:28 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@7d91e9c9 +2025-10-23 17:11:28 [http-nio-8084-exec-3] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login +2025-10-23 17:11:28 [http-nio-8084-exec-4] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.security.web.FilterChainProxy - Securing GET /swagger-ui.html +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.s.w.s.HttpSessionRequestCache - Saved request http://localhost:8084/swagger-ui.html?continue to session +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@49c72fb7, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]] +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@7d91e9c9 +2025-10-23 17:11:43 [http-nio-8084-exec-5] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login +2025-10-23 17:11:43 [http-nio-8084-exec-6] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login +2025-10-23 17:11:43 [http-nio-8084-exec-7] DEBUG o.s.security.web.FilterChainProxy - Securing GET /favicon.ico +2025-10-23 17:11:43 [http-nio-8084-exec-7] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext +2025-10-23 17:11:43 [http-nio-8084-exec-7] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@49c72fb7, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]] +2025-10-23 17:11:43 [http-nio-8084-exec-7] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@7d91e9c9 +2025-10-23 17:11:43 [http-nio-8084-exec-7] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login +2025-10-23 17:11:43 [http-nio-8084-exec-8] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login +2025-10-23 17:12:37 [SpringApplicationShutdownHook] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' +2025-10-23 17:12:37 [SpringApplicationShutdownHook] TRACE o.h.type.spi.TypeConfiguration$Scope - Handling #sessionFactoryClosed from [org.hibernate.internal.SessionFactoryImpl@263f6e96] for TypeConfiguration +2025-10-23 17:12:37 [SpringApplicationShutdownHook] DEBUG o.h.type.spi.TypeConfiguration$Scope - Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@7aa91cdd] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@263f6e96] +2025-10-23 17:12:37 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated... +2025-10-23 17:12:37 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed. diff --git a/stt/build.gradle b/stt/build.gradle index d1c1033..42d3f2c 100644 --- a/stt/build.gradle +++ b/stt/build.gradle @@ -3,6 +3,18 @@ bootJar { } dependencies { + // Common module + implementation project(':common') + + // Spring Boot starters + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + // Database + runtimeOnly 'org.postgresql:postgresql' + // Azure Speech SDK implementation "com.microsoft.cognitiveservices.speech:client-sdk:${azureSpeechVersion}" @@ -14,4 +26,11 @@ dependencies { // WebSocket implementation 'org.springframework.boot:spring-boot-starter-websocket' + + // Test dependencies + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'com.h2database:h2' + testImplementation('it.ozimov:embedded-redis:0.7.3') { + exclude group: 'org.slf4j', module: 'slf4j-simple' + } } diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/controller/SpeakerController.java b/stt/src/main/java/com/unicorn/hgzero/stt/controller/SpeakerController.java deleted file mode 100644 index 4bc4aa8..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/controller/SpeakerController.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.unicorn.hgzero.stt.controller; - -import com.unicorn.hgzero.common.dto.ApiResponse; -import com.unicorn.hgzero.stt.dto.SpeakerDto; -import com.unicorn.hgzero.stt.service.SpeakerService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import jakarta.validation.Valid; - -/** - * 화자 관리 컨트롤러 - * 화자 식별 및 관리 기능을 제공 - */ -@Slf4j -@RestController -@RequestMapping("/api/v1/stt/speakers") -@RequiredArgsConstructor -@Validated -@Tag(name = "화자 관리", description = "화자 식별 및 관리 API") -public class SpeakerController { - - private final SpeakerService speakerService; - - @Operation( - summary = "화자 식별", - description = "음성 데이터로부터 화자를 식별합니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "화자 식별 성공", - content = @Content(schema = @Schema(implementation = SpeakerDto.IdentificationResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "400", - description = "잘못된 요청" - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "404", - description = "녹음을 찾을 수 없음" - ) - }) - @PostMapping("/identify") - public ResponseEntity> identifySpeaker( - @Valid @RequestBody SpeakerDto.IdentifyRequest request) { - log.info("화자 식별 요청 - recordingId: {}", request.getRecordingId()); - - SpeakerDto.IdentificationResponse response = speakerService.identifySpeaker(request); - - return ResponseEntity.ok(ApiResponse.success(response)); - } - - @Operation( - summary = "화자 정보 조회", - description = "화자의 상세 정보를 조회합니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "조회 성공", - content = @Content(schema = @Schema(implementation = SpeakerDto.DetailResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "404", - description = "화자를 찾을 수 없음" - ) - }) - @GetMapping("/{speakerId}") - public ResponseEntity> getSpeaker( - @Parameter(description = "화자 ID", required = true) - @PathVariable String speakerId) { - log.debug("화자 조회 요청 - speakerId: {}", speakerId); - - SpeakerDto.DetailResponse response = speakerService.getSpeaker(speakerId); - - return ResponseEntity.ok(ApiResponse.success(response)); - } - - @Operation( - summary = "화자 정보 수정", - description = "화자의 이름 및 사용자 연결 정보를 수정합니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "수정 성공", - content = @Content(schema = @Schema(implementation = SpeakerDto.DetailResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "400", - description = "잘못된 요청" - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "404", - description = "화자를 찾을 수 없음" - ) - }) - @PutMapping("/{speakerId}") - public ResponseEntity> updateSpeaker( - @Parameter(description = "화자 ID", required = true) - @PathVariable String speakerId, - @Valid @RequestBody SpeakerDto.UpdateRequest request) { - log.info("화자 정보 수정 요청 - speakerId: {}, speakerName: {}", - speakerId, request.getSpeakerName()); - - SpeakerDto.DetailResponse response = speakerService.updateSpeaker(speakerId, request); - - return ResponseEntity.ok(ApiResponse.success(response)); - } - - @Operation( - summary = "녹음별 화자 목록 조회", - description = "특정 녹음에 참여한 화자 목록과 통계를 조회합니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "조회 성공", - content = @Content(schema = @Schema(implementation = SpeakerDto.ListResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "404", - description = "녹음을 찾을 수 없음" - ) - }) - @GetMapping("/recordings/{recordingId}") - public ResponseEntity> getRecordingSpeakers( - @Parameter(description = "녹음 ID", required = true) - @PathVariable String recordingId) { - log.debug("녹음별 화자 목록 조회 요청 - recordingId: {}", recordingId); - - SpeakerDto.ListResponse response = speakerService.getRecordingSpeakers(recordingId); - - return ResponseEntity.ok(ApiResponse.success(response)); - } -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/controller/TranscriptionController.java b/stt/src/main/java/com/unicorn/hgzero/stt/controller/TranscriptionController.java index eb9e1a6..6680b43 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/controller/TranscriptionController.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/controller/TranscriptionController.java @@ -12,11 +12,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import jakarta.validation.Valid; @@ -64,64 +62,7 @@ public class TranscriptionController { return ResponseEntity.ok(ApiResponse.success(response)); } - @Operation( - summary = "배치 음성 변환", - description = "오디오 파일을 업로드하여 배치 변환 작업을 시작합니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "배치 작업 시작 성공", - content = @Content(schema = @Schema(implementation = TranscriptionDto.BatchResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "400", - description = "잘못된 파일 형식 또는 요청" - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "404", - description = "녹음 세션을 찾을 수 없음" - ) - }) - @PostMapping(value = "/batch", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity> transcribeAudioBatch( - @Parameter(description = "배치 변환 요청 정보") - @Valid @RequestPart("request") TranscriptionDto.BatchRequest request, - @Parameter(description = "변환할 오디오 파일") - @RequestPart("audioFile") MultipartFile audioFile) { - log.info("배치 음성 변환 요청 - recordingId: {}, fileSize: {}", - request.getRecordingId(), audioFile.getSize()); - - TranscriptionDto.BatchResponse response = transcriptionService.transcribeAudioBatch(request, audioFile); - - return ResponseEntity.ok(ApiResponse.success(response)); - } - @Operation( - summary = "배치 변환 완료 콜백", - description = "Azure 배치 변환 완료 시 호출되는 콜백 엔드포인트입니다." - ) - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "콜백 처리 성공", - content = @Content(schema = @Schema(implementation = TranscriptionDto.CompleteResponse.class)) - ), - @io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "400", - description = "잘못된 콜백 데이터" - ) - }) - @PostMapping("/batch/callback") - public ResponseEntity> processBatchCallback( - @Valid @RequestBody TranscriptionDto.BatchCallbackRequest request) { - log.info("배치 변환 콜백 처리 - jobId: {}, status: {}", - request.getJobId(), request.getStatus()); - - TranscriptionDto.CompleteResponse response = transcriptionService.processBatchCallback(request); - - return ResponseEntity.ok(ApiResponse.success(response)); - } @Operation( summary = "변환 결과 조회", @@ -141,16 +82,11 @@ public class TranscriptionController { @GetMapping("/{recordingId}") public ResponseEntity> getTranscription( @Parameter(description = "녹음 ID", required = true) - @PathVariable String recordingId, - @Parameter(description = "세그먼트 정보 포함 여부") - @RequestParam(required = false, defaultValue = "false") Boolean includeSegments, - @Parameter(description = "특정 화자 필터") - @RequestParam(required = false) String speakerId) { - log.debug("변환 결과 조회 요청 - recordingId: {}, includeSegments: {}, speakerId: {}", - recordingId, includeSegments, speakerId); - - TranscriptionDto.Response response = transcriptionService.getTranscription(recordingId, includeSegments, speakerId); - + @PathVariable String recordingId) { + log.debug("변환 결과 조회 요청 - recordingId: {}", recordingId); + + TranscriptionDto.Response response = transcriptionService.getTranscription(recordingId); + return ResponseEntity.ok(ApiResponse.success(response)); } } \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/domain/Recording.java b/stt/src/main/java/com/unicorn/hgzero/stt/domain/Recording.java index 8bccb0a..7962d31 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/domain/Recording.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/domain/Recording.java @@ -49,17 +49,7 @@ public class Recording { * 녹음 시간 (초) */ private final Integer duration; - - /** - * 파일 크기 (bytes) - */ - private final Long fileSize; - - /** - * 저장 경로 - */ - private final String storagePath; - + /** * 언어 설정 */ diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/domain/Speaker.java b/stt/src/main/java/com/unicorn/hgzero/stt/domain/Speaker.java deleted file mode 100644 index 88b1201..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/domain/Speaker.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.unicorn.hgzero.stt.domain; - -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; - -import java.time.LocalDateTime; - -/** - * 화자 도메인 모델 - * 음성 화자 정보를 나타내는 도메인 객체 - */ -@Getter -@Builder -@ToString -public class Speaker { - - /** - * 화자 ID - */ - private final String speakerId; - - /** - * 화자 이름 - */ - private final String speakerName; - - /** - * Azure Speaker Profile ID - */ - private final String profileId; - - /** - * 연결된 사용자 ID - */ - private final String userId; - - /** - * 총 발언 세그먼트 수 - */ - private final Integer totalSegments; - - /** - * 총 발언 시간 (초) - */ - private final Integer totalDuration; - - /** - * 평균 식별 신뢰도 - */ - private final Double averageConfidence; - - /** - * 최초 등장 시간 - */ - private final LocalDateTime firstAppeared; - - /** - * 최근 등장 시간 - */ - private final LocalDateTime lastAppeared; - - /** - * 생성 시간 - */ - private final LocalDateTime createdAt; - - /** - * 수정 시간 - */ - private final LocalDateTime updatedAt; -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/dto/RecordingDto.java b/stt/src/main/java/com/unicorn/hgzero/stt/dto/RecordingDto.java index 94eb212..0c6ddbb 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/dto/RecordingDto.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/dto/RecordingDto.java @@ -45,12 +45,11 @@ public class RecordingDto { @Builder @ToString public static class PrepareResponse { - + private final String recordingId; private final String sessionId; private final String status; private final String streamUrl; - private final String storagePath; private final Integer estimatedInitTime; } @@ -89,14 +88,12 @@ public class RecordingDto { @Builder @ToString public static class StatusResponse { - + private final String recordingId; private final String status; private final LocalDateTime startTime; private final LocalDateTime endTime; private final Integer duration; - private final Long fileSize; - private final String storagePath; } /** @@ -106,7 +103,7 @@ public class RecordingDto { @Builder @ToString public static class DetailResponse { - + private final String recordingId; private final String meetingId; private final String sessionId; @@ -116,7 +113,6 @@ public class RecordingDto { private final Integer duration; private final Integer speakerCount; private final Integer segmentCount; - private final String storagePath; private final String language; } } \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/dto/SpeakerDto.java b/stt/src/main/java/com/unicorn/hgzero/stt/dto/SpeakerDto.java deleted file mode 100644 index d087bc5..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/dto/SpeakerDto.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.unicorn.hgzero.stt.dto; - -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.DecimalMax; -import jakarta.validation.constraints.DecimalMin; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 화자 관련 DTO 클래스들 - */ -public class SpeakerDto { - - /** - * 화자 식별 요청 DTO - */ - @Getter - @Builder - @ToString - public static class IdentifyRequest { - - @NotBlank(message = "녹음 ID는 필수입니다") - private final String recordingId; - - @NotBlank(message = "오디오 프레임은 필수입니다") - private final String audioFrame; - - private final Long timestamp; - } - - /** - * 화자 식별 응답 DTO - */ - @Getter - @Builder - @ToString - public static class IdentificationResponse { - - private final String speakerId; - private final String speakerName; - private final Double confidence; - private final Boolean isNewSpeaker; - private final String profileId; - } - - /** - * 화자 상세 응답 DTO - */ - @Getter - @Builder - @ToString - public static class DetailResponse { - - private final String speakerId; - private final String speakerName; - private final String profileId; - private final String userId; - private final Integer totalSegments; - private final Integer totalDuration; - private final Double averageConfidence; - private final LocalDateTime firstAppeared; - private final LocalDateTime lastAppeared; - } - - /** - * 화자 정보 업데이트 요청 DTO - */ - @Getter - @Builder - @ToString - public static class UpdateRequest { - - private final String speakerName; - private final String userId; - } - - /** - * 화자 목록 응답 DTO - */ - @Getter - @Builder - @ToString - public static class ListResponse { - - private final String recordingId; - private final Integer speakerCount; - private final List speakers; - } - - /** - * 화자 요약 DTO - */ - @Getter - @Builder - @ToString - public static class SpeakerSummary { - - private final String speakerId; - private final String speakerName; - private final Integer segmentCount; - private final Integer totalDuration; - private final Double speakingRatio; - } -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/event/RecordingEvent.java b/stt/src/main/java/com/unicorn/hgzero/stt/event/RecordingEvent.java index 7ac848f..cddb0f2 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/event/RecordingEvent.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/event/RecordingEvent.java @@ -62,12 +62,10 @@ public class RecordingEvent { private LocalDateTime startTime; private LocalDateTime endTime; private Integer duration; - private Long fileSize; - private String storagePath; private LocalDateTime eventTime; - + public static RecordingStopped of(String recordingId, String meetingId, String stoppedBy, - LocalDateTime startTime, Integer duration, Long fileSize, String storagePath) { + LocalDateTime startTime, Integer duration) { return RecordingStopped.builder() .eventId(java.util.UUID.randomUUID().toString()) .eventType("RecordingStopped") @@ -77,8 +75,6 @@ public class RecordingEvent { .startTime(startTime) .endTime(LocalDateTime.now()) .duration(duration) - .fileSize(fileSize) - .storagePath(storagePath) .eventTime(LocalDateTime.now()) .build(); } diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/event/SpeakerEvent.java b/stt/src/main/java/com/unicorn/hgzero/stt/event/SpeakerEvent.java deleted file mode 100644 index 328c8f1..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/event/SpeakerEvent.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.unicorn.hgzero.stt.event; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -/** - * 화자 관련 이벤트 정의 - */ -public class SpeakerEvent { - - /** - * 신규 화자 식별 이벤트 - */ - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class NewSpeakerIdentified { - private String eventId; - private String eventType; - private String speakerId; - private String speakerName; - private String profileId; - private String recordingId; - private String meetingId; - private Double confidence; - private LocalDateTime firstAppeared; - private LocalDateTime eventTime; - - public static NewSpeakerIdentified of(String speakerId, String speakerName, String profileId, - String recordingId, String meetingId, Double confidence) { - return NewSpeakerIdentified.builder() - .eventId(java.util.UUID.randomUUID().toString()) - .eventType("NewSpeakerIdentified") - .speakerId(speakerId) - .speakerName(speakerName) - .profileId(profileId) - .recordingId(recordingId) - .meetingId(meetingId) - .confidence(confidence) - .firstAppeared(LocalDateTime.now()) - .eventTime(LocalDateTime.now()) - .build(); - } - } - - /** - * 화자 정보 업데이트 이벤트 - */ - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class SpeakerUpdated { - private String eventId; - private String eventType; - private String speakerId; - private String oldSpeakerName; - private String newSpeakerName; - private String oldUserId; - private String newUserId; - private String updatedBy; - private LocalDateTime eventTime; - - public static SpeakerUpdated of(String speakerId, String oldSpeakerName, String newSpeakerName, - String oldUserId, String newUserId, String updatedBy) { - return SpeakerUpdated.builder() - .eventId(java.util.UUID.randomUUID().toString()) - .eventType("SpeakerUpdated") - .speakerId(speakerId) - .oldSpeakerName(oldSpeakerName) - .newSpeakerName(newSpeakerName) - .oldUserId(oldUserId) - .newUserId(newUserId) - .updatedBy(updatedBy) - .eventTime(LocalDateTime.now()) - .build(); - } - } - - /** - * 화자 통계 업데이트 이벤트 - */ - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class SpeakerStatisticsUpdated { - private String eventId; - private String eventType; - private String speakerId; - private String recordingId; - private String meetingId; - private Integer totalSegments; - private Integer totalDuration; - private Double averageConfidence; - private LocalDateTime lastAppeared; - private LocalDateTime eventTime; - - public static SpeakerStatisticsUpdated of(String speakerId, String recordingId, String meetingId, - Integer totalSegments, Integer totalDuration, Double averageConfidence) { - return SpeakerStatisticsUpdated.builder() - .eventId(java.util.UUID.randomUUID().toString()) - .eventType("SpeakerStatisticsUpdated") - .speakerId(speakerId) - .recordingId(recordingId) - .meetingId(meetingId) - .totalSegments(totalSegments) - .totalDuration(totalDuration) - .averageConfidence(averageConfidence) - .lastAppeared(LocalDateTime.now()) - .eventTime(LocalDateTime.now()) - .build(); - } - } -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/RecordingEntity.java b/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/RecordingEntity.java index 5f5c82a..c426d42 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/RecordingEntity.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/RecordingEntity.java @@ -42,13 +42,7 @@ public class RecordingEntity extends BaseTimeEntity { @Column(name = "duration") private Integer duration; - - @Column(name = "file_size") - private Long fileSize; - - @Column(name = "storage_path", length = 500) - private String storagePath; - + @Column(name = "language", length = 10, nullable = false) private String language; @@ -70,8 +64,6 @@ public class RecordingEntity extends BaseTimeEntity { .startTime(startTime) .endTime(endTime) .duration(duration) - .fileSize(fileSize) - .storagePath(storagePath) .language(language) .speakerCount(speakerCount) .segmentCount(segmentCount) @@ -90,8 +82,6 @@ public class RecordingEntity extends BaseTimeEntity { .startTime(recording.getStartTime()) .endTime(recording.getEndTime()) .duration(recording.getDuration()) - .fileSize(recording.getFileSize()) - .storagePath(recording.getStoragePath()) .language(recording.getLanguage()) .speakerCount(recording.getSpeakerCount()) .segmentCount(recording.getSegmentCount()) diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/SpeakerEntity.java b/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/SpeakerEntity.java deleted file mode 100644 index 69488fd..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/repository/entity/SpeakerEntity.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.unicorn.hgzero.stt.repository.entity; - -import com.unicorn.hgzero.common.entity.BaseTimeEntity; -import com.unicorn.hgzero.stt.domain.Speaker; -import jakarta.persistence.*; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * 화자 엔티티 - * 음성 화자 정보를 저장하는 JPA 엔티티 - */ -@Entity -@Table(name = "speakers") -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -@Builder -@ToString -public class SpeakerEntity extends BaseTimeEntity { - - @Id - @Column(name = "speaker_id", length = 50) - private String speakerId; - - @Column(name = "speaker_name", length = 100) - private String speakerName; - - @Column(name = "profile_id", length = 100) - private String profileId; - - @Column(name = "user_id", length = 50) - private String userId; - - @Column(name = "total_segments") - private Integer totalSegments; - - @Column(name = "total_duration") - private Integer totalDuration; - - @Column(name = "average_confidence") - private Double averageConfidence; - - @Column(name = "first_appeared") - private LocalDateTime firstAppeared; - - @Column(name = "last_appeared") - private LocalDateTime lastAppeared; - - /** - * 도메인 객체로 변환 - */ - public Speaker toDomain() { - return Speaker.builder() - .speakerId(speakerId) - .speakerName(speakerName) - .profileId(profileId) - .userId(userId) - .totalSegments(totalSegments) - .totalDuration(totalDuration) - .averageConfidence(averageConfidence) - .firstAppeared(firstAppeared) - .lastAppeared(lastAppeared) - .createdAt(getCreatedAt()) - .updatedAt(getUpdatedAt()) - .build(); - } - - /** - * 도메인 객체에서 엔티티 생성 - */ - public static SpeakerEntity fromDomain(Speaker speaker) { - return SpeakerEntity.builder() - .speakerId(speaker.getSpeakerId()) - .speakerName(speaker.getSpeakerName()) - .profileId(speaker.getProfileId()) - .userId(speaker.getUserId()) - .totalSegments(speaker.getTotalSegments()) - .totalDuration(speaker.getTotalDuration()) - .averageConfidence(speaker.getAverageConfidence()) - .firstAppeared(speaker.getFirstAppeared()) - .lastAppeared(speaker.getLastAppeared()) - .build(); - } - - /** - * 화자 정보 업데이트 - */ - public void updateSpeakerInfo(String speakerName, String userId) { - this.speakerName = speakerName; - this.userId = userId; - } - - /** - * 통계 정보 업데이트 - */ - public void updateStatistics(Integer totalSegments, Integer totalDuration, Double averageConfidence) { - this.totalSegments = totalSegments; - this.totalDuration = totalDuration; - this.averageConfidence = averageConfidence; - this.lastAppeared = LocalDateTime.now(); - } -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/repository/jpa/SpeakerRepository.java b/stt/src/main/java/com/unicorn/hgzero/stt/repository/jpa/SpeakerRepository.java deleted file mode 100644 index 2a6fa91..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/repository/jpa/SpeakerRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.unicorn.hgzero.stt.repository.jpa; - -import com.unicorn.hgzero.stt.repository.entity.SpeakerEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -/** - * 화자 JPA Repository - * 화자 정보에 대한 데이터베이스 접근을 담당 - */ -@Repository -public interface SpeakerRepository extends JpaRepository { - - /** - * 사용자 ID로 화자 조회 - */ - Optional findByUserId(String userId); - - /** - * Azure Profile ID로 화자 조회 - */ - Optional findByProfileId(String profileId); - - /** - * 화자명으로 검색 - */ - List findBySpeakerNameContaining(String speakerName); - - /** - * 발언 비중이 높은 화자 조회 - */ - @Query("SELECT s FROM SpeakerEntity s WHERE s.totalDuration > :minDuration ORDER BY s.totalDuration DESC") - List findActiveSpeakers(@Param("minDuration") Integer minDuration); - - /** - * 신뢰도가 낮은 화자 조회 - */ - @Query("SELECT s FROM SpeakerEntity s WHERE s.averageConfidence < :threshold ORDER BY s.averageConfidence ASC") - List findLowConfidenceSpeakers(@Param("threshold") Double threshold); - - /** - * 사용자 ID 미지정 화자 조회 - */ - @Query("SELECT s FROM SpeakerEntity s WHERE s.userId IS NULL ORDER BY s.totalDuration DESC") - List findUnassignedSpeakers(); -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/service/RecordingServiceImpl.java b/stt/src/main/java/com/unicorn/hgzero/stt/service/RecordingServiceImpl.java index 42dac6f..ff47ce5 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/service/RecordingServiceImpl.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/service/RecordingServiceImpl.java @@ -50,7 +50,6 @@ public class RecordingServiceImpl implements RecordingService { .language(request.getLanguage() != null ? request.getLanguage() : "ko-KR") .speakerCount(0) .segmentCount(0) - .storagePath(generateStoragePath(request.getMeetingId(), request.getSessionId())) .build(); recordingRepository.save(recording); @@ -65,7 +64,6 @@ public class RecordingServiceImpl implements RecordingService { .sessionId(request.getSessionId()) .status("READY") .streamUrl(streamUrl) - .storagePath(recording.getStoragePath()) .estimatedInitTime(1100) .build(); } @@ -116,17 +114,16 @@ public class RecordingServiceImpl implements RecordingService { // 녹음 중지 처리 recording.updateStatus(Recording.RecordingStatus.STOPPED); LocalDateTime endTime = LocalDateTime.now(); - + // 녹음 시간 계산 (임시로 30분으로 설정) Integer duration = 1800; // 실제로는 startTime과 endTime 차이 계산 - Long fileSize = 172800000L; // 실제로는 Azure Blob에서 파일 크기 조회 - + RecordingEntity savedRecording = recordingRepository.save(recording); - - // 녹음 중지 이벤트 발행 + + // 녹음 중지 이벤트 발행 (음성 파일 저장하지 않으므로 파일 정보 제외) RecordingEvent.RecordingStopped event = RecordingEvent.RecordingStopped.of( recordingId, recording.getMeetingId(), request.getStoppedBy(), - recording.getStartTime(), duration, fileSize, recording.getStoragePath() + recording.getStartTime(), duration ); eventPublisher.publishAsync("recording-events", event); @@ -138,8 +135,6 @@ public class RecordingServiceImpl implements RecordingService { .startTime(recording.getStartTime()) .endTime(endTime) .duration(duration) - .fileSize(fileSize) - .storagePath(recording.getStoragePath()) .build(); } @@ -160,7 +155,6 @@ public class RecordingServiceImpl implements RecordingService { .duration(recording.getDuration()) .speakerCount(recording.getSpeakerCount()) .segmentCount(recording.getSegmentCount()) - .storagePath(recording.getStoragePath()) .language(recording.getLanguage()) .build(); } @@ -181,10 +175,4 @@ public class RecordingServiceImpl implements RecordingService { String.format("%03d", (int)(Math.random() * 1000)); } - /** - * 저장 경로 생성 - */ - private String generateStoragePath(String meetingId, String sessionId) { - return String.format("recordings/%s/%s.wav", meetingId, sessionId); - } } \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerService.java b/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerService.java deleted file mode 100644 index 30b0d3b..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerService.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.unicorn.hgzero.stt.service; - -import com.unicorn.hgzero.stt.dto.SpeakerDto; - -/** - * 화자 서비스 인터페이스 - * 화자 식별 및 관리 기능을 정의 - */ -public interface SpeakerService { - - /** - * 화자 식별 - * - * @param request 화자 식별 요청 - * @return 화자 식별 응답 - */ - SpeakerDto.IdentificationResponse identifySpeaker(SpeakerDto.IdentifyRequest request); - - /** - * 화자 정보 조회 - * - * @param speakerId 화자 ID - * @return 화자 상세 응답 - */ - SpeakerDto.DetailResponse getSpeaker(String speakerId); - - /** - * 화자 정보 업데이트 - * - * @param speakerId 화자 ID - * @param request 화자 업데이트 요청 - * @return 화자 상세 응답 - */ - SpeakerDto.DetailResponse updateSpeaker(String speakerId, SpeakerDto.UpdateRequest request); - - /** - * 녹음의 화자 목록 조회 - * - * @param recordingId 녹음 ID - * @return 화자 목록 응답 - */ - SpeakerDto.ListResponse getRecordingSpeakers(String recordingId); -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerServiceImpl.java b/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerServiceImpl.java deleted file mode 100644 index 5c0d539..0000000 --- a/stt/src/main/java/com/unicorn/hgzero/stt/service/SpeakerServiceImpl.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.unicorn.hgzero.stt.service; - -import com.unicorn.hgzero.common.exception.BusinessException; -import com.unicorn.hgzero.common.exception.ErrorCode; -import com.unicorn.hgzero.stt.dto.SpeakerDto; -import com.unicorn.hgzero.stt.event.SpeakerEvent; -import com.unicorn.hgzero.stt.event.publisher.EventPublisher; -import com.unicorn.hgzero.stt.repository.entity.SpeakerEntity; -import com.unicorn.hgzero.stt.repository.jpa.SpeakerRepository; -import com.unicorn.hgzero.stt.repository.jpa.TranscriptSegmentRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * 화자 서비스 구현체 - * 화자 식별 및 관리 기능을 구현 - */ -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional -public class SpeakerServiceImpl implements SpeakerService { - - private final SpeakerRepository speakerRepository; - private final TranscriptSegmentRepository segmentRepository; - private final EventPublisher eventPublisher; - - @Override - public SpeakerDto.IdentificationResponse identifySpeaker(SpeakerDto.IdentifyRequest request) { - log.info("화자 식별 시작 - recordingId: {}", request.getRecordingId()); - - // Azure Speaker Recognition API 호출 시뮬레이션 - String profileId = simulateAzureSpeakerRecognition(request.getAudioFrame()); - Double confidence = simulateIdentificationConfidence(); - - // 기존 화자 조회 - SpeakerEntity speaker = speakerRepository.findByProfileId(profileId).orElse(null); - boolean isNewSpeaker = false; - - if (speaker == null) { - // 신규 화자 등록 - String speakerId = generateSpeakerId(); - String speakerName = "화자-" + speakerId.substring(4); - - speaker = SpeakerEntity.builder() - .speakerId(speakerId) - .speakerName(speakerName) - .profileId(profileId) - .totalSegments(0) - .totalDuration(0) - .averageConfidence(confidence) - .firstAppeared(LocalDateTime.now()) - .lastAppeared(LocalDateTime.now()) - .build(); - - speakerRepository.save(speaker); - isNewSpeaker = true; - - // 신규 화자 식별 이벤트 발행 - SpeakerEvent.NewSpeakerIdentified event = SpeakerEvent.NewSpeakerIdentified.of( - speakerId, speakerName, profileId, request.getRecordingId(), - extractMeetingIdFromRecordingId(request.getRecordingId()), confidence - ); - eventPublisher.publishAsync("speaker-events", event); - - log.info("신규 화자 등록 완료 - speakerId: {}, confidence: {}", speakerId, confidence); - } else { - log.debug("기존 화자 식별 - speakerId: {}, confidence: {}", speaker.getSpeakerId(), confidence); - } - - return SpeakerDto.IdentificationResponse.builder() - .speakerId(speaker.getSpeakerId()) - .speakerName(speaker.getSpeakerName()) - .confidence(confidence) - .isNewSpeaker(isNewSpeaker) - .profileId(profileId) - .build(); - } - - @Override - @Transactional(readOnly = true) - public SpeakerDto.DetailResponse getSpeaker(String speakerId) { - log.debug("화자 정보 조회 - speakerId: {}", speakerId); - - SpeakerEntity speaker = findSpeakerById(speakerId); - - return SpeakerDto.DetailResponse.builder() - .speakerId(speaker.getSpeakerId()) - .speakerName(speaker.getSpeakerName()) - .profileId(speaker.getProfileId()) - .userId(speaker.getUserId()) - .totalSegments(speaker.getTotalSegments()) - .totalDuration(speaker.getTotalDuration()) - .averageConfidence(speaker.getAverageConfidence()) - .firstAppeared(speaker.getFirstAppeared()) - .lastAppeared(speaker.getLastAppeared()) - .build(); - } - - @Override - public SpeakerDto.DetailResponse updateSpeaker(String speakerId, SpeakerDto.UpdateRequest request) { - log.info("화자 정보 업데이트 - speakerId: {}", speakerId); - - SpeakerEntity speaker = findSpeakerById(speakerId); - - // 화자 정보 업데이트 - String oldSpeakerName = speaker.getSpeakerName(); - String oldUserId = speaker.getUserId(); - speaker.updateSpeakerInfo(request.getSpeakerName(), request.getUserId()); - SpeakerEntity savedSpeaker = speakerRepository.save(speaker); - - // 화자 정보 업데이트 이벤트 발행 - SpeakerEvent.SpeakerUpdated event = SpeakerEvent.SpeakerUpdated.of( - speakerId, oldSpeakerName, request.getSpeakerName(), - oldUserId, request.getUserId(), "SYSTEM" - ); - eventPublisher.publishAsync("speaker-events", event); - - log.info("화자 정보 업데이트 완료 - speakerId: {}, speakerName: {}", - speakerId, request.getSpeakerName()); - - return getSpeaker(speakerId); - } - - @Override - @Transactional(readOnly = true) - public SpeakerDto.ListResponse getRecordingSpeakers(String recordingId) { - log.debug("녹음 화자 목록 조회 - recordingId: {}", recordingId); - - // 녹음별 화자 통계 조회 - List speakerStats = segmentRepository.getSpeakerStatisticsByRecording(recordingId); - - List speakers = speakerStats.stream() - .map(stat -> { - String speakerId = (String) stat[0]; - Long segmentCount = (Long) stat[1]; - Double totalDuration = (Double) stat[2]; - Double averageConfidence = (Double) stat[3]; - - // 화자 정보 조회 - SpeakerEntity speaker = speakerRepository.findById(speakerId).orElse(null); - String speakerName = speaker != null ? speaker.getSpeakerName() : "알 수 없는 화자"; - - // 발언 비율 계산 (전체 시간 대비) - Double speakingRatio = calculateSpeakingRatio(recordingId, totalDuration); - - return SpeakerDto.SpeakerSummary.builder() - .speakerId(speakerId) - .speakerName(speakerName) - .segmentCount(segmentCount.intValue()) - .totalDuration(totalDuration.intValue()) - .speakingRatio(speakingRatio) - .build(); - }) - .collect(Collectors.toList()); - - return SpeakerDto.ListResponse.builder() - .recordingId(recordingId) - .speakerCount(speakers.size()) - .speakers(speakers) - .build(); - } - - /** - * 화자 ID로 엔티티 조회 - */ - private SpeakerEntity findSpeakerById(String speakerId) { - return speakerRepository.findById(speakerId) - .orElseThrow(() -> new BusinessException(ErrorCode.ENTITY_NOT_FOUND, "화자를 찾을 수 없습니다")); - } - - /** - * 화자 ID 생성 - */ - private String generateSpeakerId() { - return "SPK-" + String.format("%03d", (int)(Math.random() * 999) + 1); - } - - /** - * Azure Speaker Recognition 시뮬레이션 - */ - private String simulateAzureSpeakerRecognition(String audioFrame) { - // 실제로는 Azure Cognitive Services Speaker Recognition API 호출 - return "PROFILE-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase(); - } - - /** - * 화자 식별 신뢰도 시뮬레이션 - */ - private Double simulateIdentificationConfidence() { - // 실제로는 Azure Speaker Recognition API에서 반환 - return 0.90 + (Math.random() * 0.10); // 0.90 ~ 1.0 - } - - /** - * 발언 비율 계산 - */ - private Double calculateSpeakingRatio(String recordingId, Double speakerDuration) { - // 전체 녹음 시간 조회 (임시로 1800초로 설정) - Double totalDuration = 1800.0; - return speakerDuration / totalDuration; - } - - /** - * 녹음 ID에서 회의 ID 추출 - */ - private String extractMeetingIdFromRecordingId(String recordingId) { - // 실제로는 Recording 엔티티에서 조회 - return "MEETING-" + recordingId.substring(4, 12); - } -} \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionService.java b/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionService.java index 75153ec..1196ab8 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionService.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionService.java @@ -2,7 +2,6 @@ package com.unicorn.hgzero.stt.service; import com.unicorn.hgzero.stt.dto.TranscriptionDto; import com.unicorn.hgzero.stt.dto.TranscriptSegmentDto; -import org.springframework.web.multipart.MultipartFile; /** * 음성 변환 서비스 인터페이스 @@ -18,30 +17,13 @@ public interface TranscriptionService { */ TranscriptSegmentDto.Response processAudioStream(TranscriptionDto.StreamRequest request); - /** - * 배치 음성-텍스트 변환 - * - * @param request 배치 변환 요청 - * @param audioFile 오디오 파일 - * @return 배치 변환 응답 - */ - TranscriptionDto.BatchResponse transcribeAudioBatch(TranscriptionDto.BatchRequest request, MultipartFile audioFile); - /** - * 배치 변환 완료 콜백 처리 - * - * @param request 배치 콜백 요청 - * @return 변환 완료 응답 - */ - TranscriptionDto.CompleteResponse processBatchCallback(TranscriptionDto.BatchCallbackRequest request); /** * 변환 텍스트 전체 조회 - * + * * @param recordingId 녹음 ID - * @param includeSegments 세그먼트 포함 여부 - * @param speakerId 화자 ID 필터 * @return 변환 결과 응답 */ - TranscriptionDto.Response getTranscription(String recordingId, Boolean includeSegments, String speakerId); + TranscriptionDto.Response getTranscription(String recordingId); } \ No newline at end of file diff --git a/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionServiceImpl.java b/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionServiceImpl.java index 1f5d66e..65648d2 100644 --- a/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionServiceImpl.java +++ b/stt/src/main/java/com/unicorn/hgzero/stt/service/TranscriptionServiceImpl.java @@ -16,9 +16,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; import java.time.LocalDateTime; +import java.time.Instant; +import java.time.ZoneId; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @@ -78,12 +79,14 @@ public class TranscriptionServiceImpl implements TranscriptionService { updateRecordingStatistics(request.getRecordingId()); // 세그먼트 생성 이벤트 발행 - LocalDateTime timestampAsLocalDateTime = java.time.Instant.ofEpochMilli(request.getTimestamp()) - .atZone(java.time.ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime timestampAsDateTime = LocalDateTime.ofInstant( + Instant.ofEpochMilli(request.getTimestamp()), + ZoneId.systemDefault() + ); TranscriptionEvent.SegmentCreated event = TranscriptionEvent.SegmentCreated.of( segmentId, request.getRecordingId(), recording.getMeetingId(), recognizedText, speakerId, "화자-" + speakerId.substring(4), - timestampAsLocalDateTime, 3.5, confidence, warningFlag + timestampAsDateTime, 3.5, confidence, warningFlag ); eventPublisher.publishAsync("transcription-events", event); @@ -111,94 +114,22 @@ public class TranscriptionServiceImpl implements TranscriptionService { .build(); } - @Override - public TranscriptionDto.BatchResponse transcribeAudioBatch(TranscriptionDto.BatchRequest request, MultipartFile audioFile) { - log.info("배치 음성 변환 시작 - recordingId: {}, fileSize: {}", - request.getRecordingId(), audioFile.getSize()); - - // 녹음 존재 확인 - RecordingEntity recording = findRecordingById(request.getRecordingId()); - - // 배치 작업 ID 생성 - String jobId = generateJobId(); - - // Azure Batch Transcription Job 생성 (실제로는 Azure Speech SDK 사용) - // 여기서는 시뮬레이션 - - log.info("배치 음성 변환 작업 생성 완료 - jobId: {}", jobId); - - return TranscriptionDto.BatchResponse.builder() - .jobId(jobId) - .recordingId(request.getRecordingId()) - .status("PROCESSING") - .estimatedCompletionTime(LocalDateTime.now().plusSeconds(30)) - .callbackUrl(request.getCallbackUrl()) - .build(); - } - - @Override - public TranscriptionDto.CompleteResponse processBatchCallback(TranscriptionDto.BatchCallbackRequest request) { - log.info("배치 변환 콜백 처리 - jobId: {}, status: {}", request.getJobId(), request.getStatus()); - - if ("COMPLETED".equals(request.getStatus()) && request.getSegments() != null) { - // 세그먼트 저장 - for (TranscriptSegmentDto.Detail segmentDto : request.getSegments()) { - String segmentId = generateSegmentId(); - - TranscriptSegmentEntity segment = TranscriptSegmentEntity.builder() - .segmentId(segmentId) - .transcriptId(segmentDto.getTranscriptId()) - .text(segmentDto.getText()) - .speakerId(segmentDto.getSpeakerId()) - .speakerName(segmentDto.getSpeakerName()) - .timestamp(segmentDto.getTimestamp()) - .duration(segmentDto.getDuration()) - .confidence(segmentDto.getConfidence()) - .warningFlag(segmentDto.getConfidence() < 0.6) - .build(); - - segmentRepository.save(segment); - } - - // 전체 텍스트 통합 및 변환 결과 저장 - String recordingId = extractRecordingIdFromJobId(request.getJobId()); - aggregateAndSaveTranscription(recordingId, request.getSegments()); - } - - return TranscriptionDto.CompleteResponse.builder() - .jobId(request.getJobId()) - .status(request.getStatus()) - .segmentCount(request.getSegments() != null ? request.getSegments().size() : 0) - .totalDuration(calculateTotalDuration(request.getSegments())) - .averageConfidence(calculateAverageConfidence(request.getSegments())) - .build(); - } @Override @Transactional(readOnly = true) - public TranscriptionDto.Response getTranscription(String recordingId, Boolean includeSegments, String speakerId) { - log.debug("변환 텍스트 조회 - recordingId: {}, includeSegments: {}", recordingId, includeSegments); - + public TranscriptionDto.Response getTranscription(String recordingId) { + log.debug("변환 텍스트 조회 - recordingId: {}", recordingId); + // 변환 결과 조회 TranscriptionEntity transcription = transcriptionRepository.findByRecordingId(recordingId) .orElseThrow(() -> new BusinessException(ErrorCode.ENTITY_NOT_FOUND, "변환 결과를 찾을 수 없습니다")); - - List segments = null; - - if (Boolean.TRUE.equals(includeSegments)) { - List segmentEntities; - - if (speakerId != null) { - segmentEntities = segmentRepository.findByRecordingIdAndSpeakerIdOrderByTimestamp(recordingId, speakerId); - } else { - segmentEntities = segmentRepository.findByRecordingIdOrderByTimestamp(recordingId); - } - - segments = segmentEntities.stream() - .map(this::convertToSegmentDetail) - .collect(Collectors.toList()); - } - + + // 세그먼트 정보 포함 + List segmentEntities = segmentRepository.findByRecordingIdOrderByTimestamp(recordingId); + List segments = segmentEntities.stream() + .map(this::convertToSegmentDetail) + .collect(Collectors.toList()); + return TranscriptionDto.Response.builder() .recordingId(recordingId) .fullText(transcription.getFullText()) diff --git a/stt/src/main/resources/application.yml b/stt/src/main/resources/application.yml index bd0c404..efe37bd 100644 --- a/stt/src/main/resources/application.yml +++ b/stt/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: datasource: url: jdbc:${DB_KIND:postgresql}://${DB_HOST:4.230.65.89}:${DB_PORT:5432}/${DB_NAME:sttdb} username: ${DB_USERNAME:hgzerouser} - password: ${DB_PASSWORD:} + password: ${DB_PASSWORD:Hi5Jessica!} driver-class-name: org.postgresql.Driver hikari: maximum-pool-size: 20 @@ -21,6 +21,7 @@ spring: show-sql: ${SHOW_SQL:true} properties: hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect format_sql: true use_sql_comments: true hibernate: @@ -31,7 +32,7 @@ spring: redis: host: ${REDIS_HOST:20.249.177.114} port: ${REDIS_PORT:6379} - password: ${REDIS_PASSWORD:} + password: ${REDIS_PASSWORD:Hi5Jessica!} timeout: 2000ms lettuce: pool: diff --git a/stt/src/test/java/com/unicorn/hgzero/stt/SttApplicationTest.java b/stt/src/test/java/com/unicorn/hgzero/stt/SttApplicationTest.java index c6c294f..07c791c 100644 --- a/stt/src/test/java/com/unicorn/hgzero/stt/SttApplicationTest.java +++ b/stt/src/test/java/com/unicorn/hgzero/stt/SttApplicationTest.java @@ -1,16 +1,19 @@ package com.unicorn.hgzero.stt; +import com.unicorn.hgzero.stt.config.TestConfig; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; /** * STT 애플리케이션 통합 테스트 * 전체 애플리케이션 컨텍스트 로딩 및 기본 설정 검증 */ -@SpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") +@Import(TestConfig.class) @DisplayName("STT 애플리케이션 테스트") class SttApplicationTest { diff --git a/stt/src/test/java/com/unicorn/hgzero/stt/controller/RecordingControllerTest.java b/stt/src/test/java/com/unicorn/hgzero/stt/controller/RecordingControllerTest.java index 20866f8..c1ab742 100644 --- a/stt/src/test/java/com/unicorn/hgzero/stt/controller/RecordingControllerTest.java +++ b/stt/src/test/java/com/unicorn/hgzero/stt/controller/RecordingControllerTest.java @@ -1,6 +1,7 @@ package com.unicorn.hgzero.stt.controller; import com.fasterxml.jackson.databind.ObjectMapper; +import com.unicorn.hgzero.stt.config.WebMvcTestConfig; import com.unicorn.hgzero.stt.dto.RecordingDto; import com.unicorn.hgzero.stt.service.RecordingService; import org.junit.jupiter.api.BeforeEach; @@ -9,6 +10,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -25,13 +27,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @WebMvcTest(RecordingController.class) @DisplayName("녹음 컨트롤러 테스트") class RecordingControllerTest { - + @Autowired private MockMvc mockMvc; - + @Autowired private ObjectMapper objectMapper; - + @MockBean private RecordingService recordingService; diff --git a/stt/src/test/java/com/unicorn/hgzero/stt/integration/SttApiIntegrationTest.java b/stt/src/test/java/com/unicorn/hgzero/stt/integration/SttApiIntegrationTest.java index a9f96ce..0461a11 100644 --- a/stt/src/test/java/com/unicorn/hgzero/stt/integration/SttApiIntegrationTest.java +++ b/stt/src/test/java/com/unicorn/hgzero/stt/integration/SttApiIntegrationTest.java @@ -1,14 +1,21 @@ package com.unicorn.hgzero.stt.integration; import com.fasterxml.jackson.databind.ObjectMapper; +import com.unicorn.hgzero.stt.config.TestConfig; import com.unicorn.hgzero.stt.dto.RecordingDto; import com.unicorn.hgzero.stt.dto.TranscriptionDto; import com.unicorn.hgzero.stt.dto.SpeakerDto; +import com.unicorn.hgzero.stt.service.RecordingService; +import com.unicorn.hgzero.stt.service.SpeakerService; +import com.unicorn.hgzero.stt.service.TranscriptionService; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -16,6 +23,8 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.transaction.annotation.Transactional; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -23,19 +32,111 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * STT API 통합 테스트 * 전체 워크플로우 시나리오 테스트 */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureWebMvc @ActiveProfiles("test") -@Transactional @DisplayName("STT API 통합 테스트") class SttApiIntegrationTest { - + @Autowired private MockMvc mockMvc; - + @Autowired private ObjectMapper objectMapper; - + + @MockBean + private RecordingService recordingService; + + @MockBean + private SpeakerService speakerService; + + @MockBean + private TranscriptionService transcriptionService; + + @BeforeEach + void setUp() { + // RecordingService Mock 설정 + when(recordingService.prepareRecording(any(RecordingDto.PrepareRequest.class))) + .thenReturn(RecordingDto.PrepareResponse.builder() + .recordingId("REC-20250123-001") + .sessionId("SESSION-INTEGRATION-001") + .status("READY") + .streamUrl("wss://api.example.com/stt/v1/ws/stt/SESSION-INTEGRATION-001") + .storagePath("recordings/MEETING-INTEGRATION-001/SESSION-INTEGRATION-001.wav") + .estimatedInitTime(1100) + .build()); + + when(recordingService.startRecording(anyString(), any(RecordingDto.StartRequest.class))) + .thenReturn(RecordingDto.StatusResponse.builder() + .recordingId("REC-20250123-001") + .status("RECORDING") + .startTime(java.time.LocalDateTime.now()) + .duration(0) + .build()); + + when(recordingService.stopRecording(anyString(), any(RecordingDto.StopRequest.class))) + .thenReturn(RecordingDto.StatusResponse.builder() + .recordingId("REC-20250123-001") + .status("STOPPED") + .startTime(java.time.LocalDateTime.now().minusMinutes(30)) + .endTime(java.time.LocalDateTime.now()) + .duration(1800) + .fileSize(172800000L) + .storagePath("recordings/MEETING-INTEGRATION-001/SESSION-INTEGRATION-001.wav") + .build()); + + when(recordingService.getRecording(anyString())) + .thenReturn(RecordingDto.DetailResponse.builder() + .recordingId("REC-20250123-001") + .meetingId("MEETING-INTEGRATION-001") + .sessionId("SESSION-INTEGRATION-001") + .status("STOPPED") + .startTime(java.time.LocalDateTime.now().minusMinutes(30)) + .endTime(java.time.LocalDateTime.now()) + .duration(1800) + .speakerCount(3) + .segmentCount(45) + .storagePath("recordings/MEETING-INTEGRATION-001/SESSION-INTEGRATION-001.wav") + .language("ko-KR") + .build()); + + // TranscriptionService Mock 설정 + when(transcriptionService.processAudioStream(any(TranscriptionDto.StreamRequest.class))) + .thenReturn(com.unicorn.hgzero.stt.dto.TranscriptSegmentDto.Response.builder() + .recordingId("REC-20250123-001") + .transcriptId("TRANS-001") + .text("안녕하세요") + .confidence(0.95) + .timestamp(System.currentTimeMillis()) + .speakerId("SPK-001") + .duration(2.5) + .build()); + + when(transcriptionService.getTranscription(anyString(), any(), any())) + .thenReturn(TranscriptionDto.Response.builder() + .recordingId("REC-20250123-001") + .fullText("안녕하세요. 오늘 회의를 시작하겠습니다.") + .segmentCount(45) + .speakerCount(3) + .totalDuration(1800) + .averageConfidence(0.92) + .build()); + + // SpeakerService Mock 설정 + when(speakerService.identifySpeaker(any(SpeakerDto.IdentifyRequest.class))) + .thenReturn(SpeakerDto.IdentificationResponse.builder() + .speakerId("SPK-001") + .confidence(0.95) + .isNewSpeaker(false) + .build()); + + when(speakerService.getRecordingSpeakers(anyString())) + .thenReturn(SpeakerDto.ListResponse.builder() + .recordingId("REC-20250123-001") + .speakerCount(3) + .build()); + } + @Test @DisplayName("전체 STT 워크플로우 통합 테스트") void fullSttWorkflowIntegrationTest() throws Exception { @@ -141,29 +242,40 @@ class SttApiIntegrationTest { @Test @DisplayName("에러 케이스 통합 테스트") void errorCasesIntegrationTest() throws Exception { + // 존재하지 않는 녹음에 대한 Mock 설정 + when(recordingService.startRecording(eq("NONEXISTENT-001"), any(RecordingDto.StartRequest.class))) + .thenThrow(new com.unicorn.hgzero.common.exception.BusinessException( + com.unicorn.hgzero.common.exception.ErrorCode.ENTITY_NOT_FOUND, + "녹음을 찾을 수 없습니다")); + + when(transcriptionService.getTranscription(eq("NONEXISTENT-001"), any(), any())) + .thenThrow(new com.unicorn.hgzero.common.exception.BusinessException( + com.unicorn.hgzero.common.exception.ErrorCode.ENTITY_NOT_FOUND, + "변환 결과를 찾을 수 없습니다")); + // 존재하지 않는 녹음 시작 시도 RecordingDto.StartRequest startRequest = RecordingDto.StartRequest.builder() .startedBy("test-user") .build(); - + mockMvc.perform(post("/api/v1/stt/recordings/NONEXISTENT-001/start") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(startRequest))) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.success").value(false)) .andExpect(jsonPath("$.message").exists()); - + // 잘못된 요청 데이터로 녹음 준비 시도 RecordingDto.PrepareRequest invalidRequest = RecordingDto.PrepareRequest.builder() .meetingId("") // 빈 meetingId .sessionId("SESSION-001") .build(); - + mockMvc.perform(post("/api/v1/stt/recordings/prepare") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(invalidRequest))) .andExpect(status().isBadRequest()); - + // 존재하지 않는 변환 결과 조회 mockMvc.perform(get("/api/v1/stt/transcription/NONEXISTENT-001")) .andExpect(status().isBadRequest()) diff --git a/stt/src/test/java/com/unicorn/hgzero/stt/service/TranscriptionServiceTest.java b/stt/src/test/java/com/unicorn/hgzero/stt/service/TranscriptionServiceTest.java index cc40023..1121f91 100644 --- a/stt/src/test/java/com/unicorn/hgzero/stt/service/TranscriptionServiceTest.java +++ b/stt/src/test/java/com/unicorn/hgzero/stt/service/TranscriptionServiceTest.java @@ -50,8 +50,10 @@ class TranscriptionServiceTest { private TranscriptionServiceImpl transcriptionService; private RecordingEntity recordingEntity; + private TranscriptSegmentEntity segmentEntity; + private TranscriptionEntity transcriptionEntity; private TranscriptionDto.StreamRequest streamRequest; - + @BeforeEach void setUp() { recordingEntity = RecordingEntity.builder() @@ -59,7 +61,23 @@ class TranscriptionServiceTest { .meetingId("MEETING-001") .sessionId("SESSION-001") .build(); - + + segmentEntity = TranscriptSegmentEntity.builder() + .segmentId("SEG-001") + .recordingId("REC-20250123-001") + .text("테스트 음성 변환 결과") + .timestamp(System.currentTimeMillis()) + .confidence(0.95) + .build(); + + transcriptionEntity = TranscriptionEntity.builder() + .transcriptId("TRANS-001") + .recordingId("REC-20250123-001") + .fullText("전체 음성 변환 결과") + .segmentCount(1) + .averageConfidence(0.95) + .build(); + streamRequest = TranscriptionDto.StreamRequest.builder() .recordingId("REC-20250123-001") .audioData("base64-encoded-audio-data") @@ -73,7 +91,7 @@ class TranscriptionServiceTest { void processAudioStream_Success() { // Given when(recordingRepository.findById(anyString())).thenReturn(Optional.of(recordingEntity)); - when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(any()); + when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(segmentEntity); when(segmentRepository.getSpeakerStatisticsByRecording(anyString())).thenReturn(List.of()); when(segmentRepository.countByRecordingId(anyString())).thenReturn(1L); when(recordingRepository.save(any(RecordingEntity.class))).thenReturn(recordingEntity); @@ -88,9 +106,9 @@ class TranscriptionServiceTest { assertThat(response.getConfidence()).isGreaterThan(0.8); assertThat(response.getSpeakerId()).isNotEmpty(); - verify(recordingRepository).findById("REC-20250123-001"); + verify(recordingRepository, atLeastOnce()).findById("REC-20250123-001"); verify(segmentRepository).save(any(TranscriptSegmentEntity.class)); - verify(eventPublisher).publishAsync(eq("transcription-events"), any()); + verify(eventPublisher, atLeastOnce()).publishAsync(eq("transcription-events"), any()); } @Test @@ -114,7 +132,7 @@ class TranscriptionServiceTest { void processAudioStream_LowConfidenceWarning() { // Given when(recordingRepository.findById(anyString())).thenReturn(Optional.of(recordingEntity)); - when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(any()); + when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(segmentEntity); when(segmentRepository.getSpeakerStatisticsByRecording(anyString())).thenReturn(List.of()); when(segmentRepository.countByRecordingId(anyString())).thenReturn(1L); when(recordingRepository.save(any(RecordingEntity.class))).thenReturn(recordingEntity); @@ -191,8 +209,8 @@ class TranscriptionServiceTest { .segments(segments) .build(); - when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(any()); - when(transcriptionRepository.save(any(TranscriptionEntity.class))).thenReturn(any()); + when(segmentRepository.save(any(TranscriptSegmentEntity.class))).thenReturn(segmentEntity); + when(transcriptionRepository.save(any(TranscriptionEntity.class))).thenReturn(transcriptionEntity); // When TranscriptionDto.CompleteResponse response = transcriptionService.processBatchCallback(callbackRequest); diff --git a/stt/src/test/resources/application-test.yml b/stt/src/test/resources/application-test.yml index 3060eb1..e6b283d 100644 --- a/stt/src/test/resources/application-test.yml +++ b/stt/src/test/resources/application-test.yml @@ -1,55 +1,131 @@ -# STT 서비스 테스트 설정 +# 테스트 환경별 설정 선택 +# 1. 단위 테스트용 (기본) +# 2. Docker 통합 테스트용 (integration-test profile 활성화 시) + spring: - profiles: - active: test - - # 데이터베이스 설정 (H2 인메모리) + application: + name: stt-test + + # Bean Override 허용 + main: + allow-bean-definition-overriding: true + + # In-Memory Database (기본값) datasource: - url: jdbc:h2:mem:testdb - driver-class-name: org.h2.Driver + url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE username: sa - password: - - # JPA 설정 + password: + driver-class-name: org.h2.Driver + jpa: + show-sql: false hibernate: ddl-auto: create-drop - show-sql: true properties: hibernate: dialect: org.hibernate.dialect.H2Dialect - format_sql: true - - # Redis 설정 (임베디드) - redis: - host: localhost - port: 6370 - timeout: 2000ms - - # JWT 설정 - security: - jwt: - secret: test-secret-key-for-jwt-token-generation-test - expiration: 86400 -# Azure 서비스 설정 (테스트용 더미) + # Mock Redis (handled by TestConfig) + data: + redis: + host: localhost + port: 6370 + password: + database: 0 + +# Test Server +server: + port: 0 + +# Mock Azure Services azure: speech: subscription-key: test-key - region: koreacentral - endpoint: https://test.cognitiveservices.azure.com/ - - storage: - connection-string: DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=testkey;EndpointSuffix=core.windows.net + region: eastus + language: ko-KR + blob: + connection-string: DefaultEndpointsProtocol=https;AccountName=test;AccountKey=test;EndpointSuffix=core.windows.net container-name: test-recordings - - event-hubs: - connection-string: Endpoint=sb://test-eventhub.servicebus.windows.net/;SharedAccessKeyName=test;SharedAccessKey=test + eventhub: + connection-string: Endpoint=sb://test.servicebus.windows.net/;SharedAccessKeyName=test;SharedAccessKey=test + name: test-events consumer-group: test-group -# 로깅 설정 +--- +# Docker 통합 테스트용 설정 +spring: + config: + activate: + on-profile: integration-test + + # Real PostgreSQL (via Docker) + datasource: + url: jdbc:postgresql://localhost:5433/sttdb_test + username: testuser + password: testpass + driver-class-name: org.postgresql.Driver + + jpa: + show-sql: true + hibernate: + ddl-auto: update + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + + # Real Redis (via Docker) + data: + redis: + host: localhost + port: 6380 + password: testpass + database: 0 + +# Real Server +server: + port: 8083 + +# Azure Emulator (Azurite) +azure: + speech: + subscription-key: test-key + region: eastus + language: ko-KR + blob: + connection-string: DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1; + container-name: test-recordings + eventhub: + connection-string: Endpoint=sb://test.servicebus.windows.net/;SharedAccessKeyName=test;SharedAccessKey=test + name: test-events + consumer-group: test-group + +--- +# 공통 설정 +jwt: + secret: test-secret-key-for-testing-purposes-only-not-for-production-use + access-token-validity: 3600 + refresh-token-validity: 604800 + +cors: + allowed-origins: "*" + +management: + endpoints: + enabled-by-default: false + endpoint: + health: + enabled: true + +springdoc: + api-docs: + enabled: false + swagger-ui: + enabled: false + logging: level: - com.unicorn.hgzero.stt: DEBUG - org.springframework.web: DEBUG - org.hibernate.SQL: DEBUG \ No newline at end of file + com.unicorn.hgzero.stt: INFO + org.springframework: WARN + org.hibernate: WARN + pattern: + console: "%d{HH:mm:ss} %-5level %logger{36} - %msg%n"