From 3aaa859c9e328e966800cee9fae9d6ba839d524d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Thu, 14 Aug 2025 23:31:49 +0200 Subject: [PATCH 1/8] Injection-proof solution --- .../pkwmtt/timetable/dto/DayOfWeekDTO.java | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/pkwmtt/timetable/dto/DayOfWeekDTO.java b/src/main/java/org/pkwmtt/timetable/dto/DayOfWeekDTO.java index 5ab6438..53d581b 100644 --- a/src/main/java/org/pkwmtt/timetable/dto/DayOfWeekDTO.java +++ b/src/main/java/org/pkwmtt/timetable/dto/DayOfWeekDTO.java @@ -12,28 +12,28 @@ public class DayOfWeekDTO { private final String name; private List odd; private List even; - - public DayOfWeekDTO(String name) { + + public DayOfWeekDTO (String name) { this.name = name; odd = new ArrayList<>(); even = new ArrayList<>(); } - - - public void add(SubjectDTO subjectDTO, boolean isNotOdd) { + + + public void add (SubjectDTO subjectDTO, boolean isNotOdd) { if (isNotOdd) { even.add(subjectDTO); } else { odd.add(subjectDTO); } } - - - public void deleteSubjectTypesFromNames() { + + + public void deleteSubjectTypesFromNames () { even.forEach(SubjectDTO::deleteTypeAndUnnecessaryCharactersFromName); odd.forEach(SubjectDTO::deleteTypeAndUnnecessaryCharactersFromName); } - + /** * Filters both odd- and even-week subject lists, * keeping only those entries that belong exclusively @@ -43,23 +43,24 @@ public void deleteSubjectTypesFromNames() { * where the first character is the group letter * and the last character is the subgroup number */ - public void filterByGroup(String group) { + public void filterByGroup (String group) { // Delete first character if group starts 'G' - if (group.charAt(0) == 'G' && group.length() > 3) + if (group.charAt(0) == 'G' && group.length() > 3) { group = group.substring(1); - + } + // Extract the group letter (e.g., "K" from "K03") var groupName = String.valueOf(group.charAt(0)); - + // Extract the subgroup digit (e.g., "3" from "K03") var targetNumber = String.valueOf(group.charAt(group.length() - 1)); - + // Apply the filter to both odd- and even-week lists odd = filter(odd, groupName, targetNumber); even = filter(even, groupName, targetNumber); - + } - + /** * Returns a new list containing only those SubjectDTO items * whose type string matches exclusively the target group code or doesn't have group at all. @@ -69,22 +70,16 @@ public void filterByGroup(String group) { * @param targetNumber the subgroup digit to keep (e.g., "3") * @return a filtered list of SubjectDTO */ - private List filter(List list, String groupName, String targetNumber) { - + private List filter (List list, String groupName, String targetNumber) { + list = list.stream() - // Keep only items that have no other subgroup codes - .filter( - item -> - hasOnlyTargetGroup( - item.getName(), - groupName, - targetNumber - ) - ).toList(); - + // Keep only items that have no other subgroup codes + .filter(item -> hasOnlyTargetGroup(item.getName(), groupName, targetNumber)) + .toList(); + return list; } - + /** * Checks if the given element string contains no other codes for the same group.* * @@ -93,15 +88,23 @@ private List filter(List list, String groupName, String * @param targetNumber the digit we want to allow (e.g., "3") * @return true if no non-target subgroup codes are present */ - private boolean hasOnlyTargetGroup(String element, String groupName, String targetNumber) { - var pattern = Pattern.compile(String.format("\\bG?[%s]0[1-9]\\b", groupName)); + private boolean hasOnlyTargetGroup (String element, String groupName, String targetNumber) { + var pattern = Pattern.compile(String.format( + "\\bG?[%s]0[1-9]\\b", + Pattern.quote(groupName) + )); var matcher = pattern.matcher(element); - if (!matcher.find()) + if (!matcher.find()) { return true; - - pattern = Pattern.compile(String.format("%s0%s", groupName, targetNumber)); + } + + pattern = Pattern.compile(String.format( + "%s0%s", + Pattern.quote(groupName), + Pattern.quote(targetNumber) + )); matcher = pattern.matcher(element); return matcher.find(); } - + } \ No newline at end of file From 54dc79610e2f9a0db1519df414aa81fff443c805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:03:47 +0200 Subject: [PATCH 2/8] Update application-prod.properties --- src/main/resources/application-prod.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 567cfdb..cd609c7 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -3,7 +3,7 @@ spring.datasource.username=pkttuser spring.datasource.password=pkttpassword server.port=8080 -server.address=155.133.73.101 +server.address=0.0.0.0 spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect From 5cd3cfe83d3380ef93c960e7de1fef7ffee8697e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:50:47 +0200 Subject: [PATCH 3/8] Created Email service --- Dockerfile | 2 +- logs/app.log | 1337 ----------------- pom.xml | 15 +- .../java/org/pkwmtt/mail/EmailService.java | 33 + .../org/pkwmtt/mail/EmailTempController.java | 26 + .../org/pkwmtt/mail/config/MailConfig.java | 35 + .../java/org/pkwmtt/mail/dto/MailDTO.java | 14 + src/main/resources/application.properties | 9 + 8 files changed, 132 insertions(+), 1339 deletions(-) create mode 100644 src/main/java/org/pkwmtt/mail/EmailService.java create mode 100644 src/main/java/org/pkwmtt/mail/EmailTempController.java create mode 100644 src/main/java/org/pkwmtt/mail/config/MailConfig.java create mode 100644 src/main/java/org/pkwmtt/mail/dto/MailDTO.java diff --git a/Dockerfile b/Dockerfile index 68b6119..f2676ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,4 @@ FROM amazoncorretto:21 WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 -ENTRYPOINT ["java","-Dspring.profiles.active=prod", "-jar", "app.jar"] +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/logs/app.log b/logs/app.log index c19acaf..e69de29 100644 --- a/logs/app.log +++ b/logs/app.log @@ -1,1337 +0,0 @@ -2025-08-11 23:21:48 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-11 23:21:49 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-11 23:22:35 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-11 23:25:54 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-11 23:26:11 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:28:21 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:29:24 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:31:56 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:35:09 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:36:21 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.UnsupportedOperationException] with root cause -java.lang.UnsupportedOperationException: null - at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142) - at java.base/java.util.ImmutableCollections$AbstractImmutableList.sort(ImmutableCollections.java:263) - at java.base/java.util.Collections.sort(Collections.java:145) - at org.pkwmtt.timetable.TimetableController.getListOfGeneralGroups(TimetableController.java:62) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-11 23:41:23 ERROR o.s.b.d.LoggingFailureAnalysisReporter - - -*************************** -APPLICATION FAILED TO START -*************************** - -Description: - -Parameter 0 of constructor in org.pkwmtt.temp.CacheInspectorController required a bean of type 'org.pkwmtt.timetable.TimetableService' that could not be found. - - -Action: - -Consider defining a bean of type 'org.pkwmtt.timetable.TimetableService' in your configuration. - -2025-08-11 23:58:48 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.pkwmtt.exceptions.SpecifiedSubGroupDoesntExistsException: Specified general group doesn't exists] with root cause -org.pkwmtt.exceptions.SpecifiedSubGroupDoesntExistsException: Specified general group doesn't exists - at org.pkwmtt.timetable.TimetableService.getFilteredGeneralGroupSchedule(TimetableService.java:84) - at org.pkwmtt.timetable.TimetableController.getGeneralGroupSchedule(TimetableController.java:39) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) - at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) - at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) - at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) - at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) - at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) - at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:125) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) - at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) - at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) - at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) - at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) - at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.ServletRequestPathFilter.doFilter(ServletRequestPathFilter.java:52) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebSecurityConfiguration.java:319) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$4(HandlerMappingIntrospector.java:267) - at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) - at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) - at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:240) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:114) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) - at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) - at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) - at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) - at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) - at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) - at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) - at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-08-12 00:14:42 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-12 00:14:43 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-12 00:14:58 ERROR o.s.boot.SpringApplication - Application run failed -org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.pkwmtt.PkwmttBackendApplication] - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:194) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) - at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) - at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) - at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) - at org.pkwmtt.PkwmttBackendApplication.main(PkwmttBackendApplication.java:12) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: java.lang.IllegalArgumentException: Could not find class [org.pkwmtt.timetable.TimetableController] - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:372) - at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:466) - at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) - at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:278) - at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:147) - at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:113) - at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:281) - at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) - at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:346) - at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:281) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:204) - at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:172) - ... 16 common frames omitted -Caused by: java.lang.ClassNotFoundException: org.pkwmtt.timetable.TimetableController - at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) - at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) - at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:534) - at java.base/java.lang.Class.forName(Class.java:513) - at org.springframework.util.ClassUtils.forName(ClassUtils.java:321) - at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:362) - ... 28 common frames omitted -2025-08-12 00:15:10 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:15:10 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:15:10 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:16:07 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:16:07 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:16:07 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:16:42 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. -2025-08-12 00:16:56 ERROR o.p.t.TimetableExceptionHandler - SERVICE_UNAVAILABLE # Content of university webpage is not available right now. diff --git a/pom.xml b/pom.xml index 5b85e73..1ab2d6a 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,9 @@ PKWMTT-backend 0.1.0-ALPHA PKWMTT-backend - PKWM App (Server) – timetable, exam calendar and ECTS calculator for students of Mechanical Engineering @ Cracow University of Technology + PKWM App (Server) – timetable, exam calendar and ECTS calculator for students of Mechanical Engineering + @ Cracow University of Technology + https://github.com/PKTTTeam/PKWMTT-backend @@ -147,6 +149,17 @@ wiremock-spring-boot 3.10.0 + + + org.springframework.boot + spring-boot-starter-mail + + + + io.github.cdimascio + dotenv-java + 3.0.0 + diff --git a/src/main/java/org/pkwmtt/mail/EmailService.java b/src/main/java/org/pkwmtt/mail/EmailService.java new file mode 100644 index 0000000..13b8a14 --- /dev/null +++ b/src/main/java/org/pkwmtt/mail/EmailService.java @@ -0,0 +1,33 @@ +package org.pkwmtt.mail; + +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import org.pkwmtt.mail.dto.MailDTO; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class EmailService { + + private final JavaMailSender mailSender; + + @Value("${EMAIL_USERNAME}") + private String hostEmail; + + public void send (MailDTO mail) throws MessagingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + + helper.setFrom(hostEmail); + helper.setTo(mail.getRecipient()); + helper.setText(mail.getDescription(), true); + helper.setSubject(mail.getTitle()); + + mailSender.send(message); + + } +} diff --git a/src/main/java/org/pkwmtt/mail/EmailTempController.java b/src/main/java/org/pkwmtt/mail/EmailTempController.java new file mode 100644 index 0000000..9898a23 --- /dev/null +++ b/src/main/java/org/pkwmtt/mail/EmailTempController.java @@ -0,0 +1,26 @@ +package org.pkwmtt.mail; + +import jakarta.mail.MessagingException; +import lombok.RequiredArgsConstructor; +import org.pkwmtt.mail.dto.MailDTO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/mail") +public class EmailTempController { + + private final EmailService service; + + @PostMapping + public void sendMail (@RequestParam(name = "r") String recipientEmailAddress) + throws MessagingException { + service.send(new MailDTO() + .setRecipient(recipientEmailAddress) + .setDescription("TEST") + .setTitle("TEST")); + } +} diff --git a/src/main/java/org/pkwmtt/mail/config/MailConfig.java b/src/main/java/org/pkwmtt/mail/config/MailConfig.java new file mode 100644 index 0000000..f70938f --- /dev/null +++ b/src/main/java/org/pkwmtt/mail/config/MailConfig.java @@ -0,0 +1,35 @@ +package org.pkwmtt.mail.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +@Configuration +public class MailConfig { + + @Value("${EMAIL_USERNAME}") + private String username; + @Value("${EMAIL_PASSWORD}") + private String password; + + @Bean + public JavaMailSender javaMailSender () { + + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost("smtp.gmail.com"); + mailSender.setPort(587); + mailSender.setUsername(username); + mailSender.setPassword(password); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + + return mailSender; + } +} diff --git a/src/main/java/org/pkwmtt/mail/dto/MailDTO.java b/src/main/java/org/pkwmtt/mail/dto/MailDTO.java new file mode 100644 index 0000000..215d774 --- /dev/null +++ b/src/main/java/org/pkwmtt/mail/dto/MailDTO.java @@ -0,0 +1,14 @@ +package org.pkwmtt.mail.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@NoArgsConstructor +public class MailDTO { + private String recipient; + private String title; + private String description; +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4c1aef9..af7d7de 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,6 @@ +#Import .env variables +spring.config.import=optional:file:.env[.properties] + spring.datasource.url=jdbc:mysql://localhost:3306/pktt?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC spring.datasource.username=pkttuser spring.datasource.password=pkttpassword @@ -18,3 +21,9 @@ spring.cache.type=caffeine logging.level.WireMock.my-mock=off +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +spring.mail.username=${EMAIL_USERNAME} +spring.mail.password=${EMAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true From 3d856b02c2f90f7de87570357e8a610525756c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:52:38 +0200 Subject: [PATCH 4/8] Update docker-image.yml --- .github/workflows/docker-image.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 9ccf3e8..439bed2 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -108,3 +108,6 @@ jobs: ghcr.io/${{ env.IMAGE_REPO }}:${{ github.run_number }} cache-from: type=gha cache-to: type=gha,mode=max + build-args: | + EMAIL_USERNAME=${{ secrets.EMAIL_USERNAME }} + EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }} \ No newline at end of file From 4612a1e8b38c20f987ffca154561d099983d3fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:05:36 +0200 Subject: [PATCH 5/8] Change value signature --- src/main/java/org/pkwmtt/mail/EmailService.java | 2 +- src/main/java/org/pkwmtt/mail/config/MailConfig.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/pkwmtt/mail/EmailService.java b/src/main/java/org/pkwmtt/mail/EmailService.java index 13b8a14..6d36660 100644 --- a/src/main/java/org/pkwmtt/mail/EmailService.java +++ b/src/main/java/org/pkwmtt/mail/EmailService.java @@ -15,7 +15,7 @@ public class EmailService { private final JavaMailSender mailSender; - @Value("${EMAIL_USERNAME}") + @Value("${spring.mail.username}") private String hostEmail; public void send (MailDTO mail) throws MessagingException { diff --git a/src/main/java/org/pkwmtt/mail/config/MailConfig.java b/src/main/java/org/pkwmtt/mail/config/MailConfig.java index f70938f..618dc08 100644 --- a/src/main/java/org/pkwmtt/mail/config/MailConfig.java +++ b/src/main/java/org/pkwmtt/mail/config/MailConfig.java @@ -11,9 +11,9 @@ @Configuration public class MailConfig { - @Value("${EMAIL_USERNAME}") + @Value("${spring.mail.username}") private String username; - @Value("${EMAIL_PASSWORD}") + @Value("${spring.mail.password}") private String password; @Bean From 367f1958dfb71a57d37706f9a5301efaf9df29da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:08:54 +0200 Subject: [PATCH 6/8] Update docker-image.yml --- .github/workflows/docker-image.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 439bed2..ea94ec7 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -40,6 +40,8 @@ jobs: SPRING_DATASOURCE_USERNAME: ${{ secrets.SPRING_DATASOURCE_USERNAME }} SPRING_DATASOURCE_PASSWORD: ${{ secrets.SPRING_DATASOURCE_PASSWORD }} SPRING_PROFILES_ACTIVE: ${{ secrets.SPRING_PROFILES_ACTIVE }} + EMAIL_USERNAME: ${{ secrets.EMAIL_USERNAME }} + EMAIL_PASSWORD: ${{ secrets.EMAIL_PASSWORD }} steps: - name: Checkout code From b832f3ca38b6fa6e457a8d6c28300ed44d6c6524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Sat, 16 Aug 2025 15:07:01 +0200 Subject: [PATCH 7/8] Detect if the mail server is available --- .../MailServiceNotAvailableException.java | 9 ++++++ .../java/org/pkwmtt/mail/EmailService.java | 19 ++++++++++-- .../org/pkwmtt/mail/EmailTempController.java | 19 ++++++++---- .../org/pkwmtt/mail/config/MailConfig.java | 30 ++++++++++++++++--- src/main/resources/application.properties | 4 +-- 5 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 src/main/java/org/pkwmtt/exceptions/MailServiceNotAvailableException.java diff --git a/src/main/java/org/pkwmtt/exceptions/MailServiceNotAvailableException.java b/src/main/java/org/pkwmtt/exceptions/MailServiceNotAvailableException.java new file mode 100644 index 0000000..e5f98de --- /dev/null +++ b/src/main/java/org/pkwmtt/exceptions/MailServiceNotAvailableException.java @@ -0,0 +1,9 @@ +package org.pkwmtt.exceptions; + +public class MailServiceNotAvailableException + extends RuntimeException { + public MailServiceNotAvailableException () { + super("Mail service is not available right now."); + } + +} diff --git a/src/main/java/org/pkwmtt/mail/EmailService.java b/src/main/java/org/pkwmtt/mail/EmailService.java index 6d36660..1174ec0 100644 --- a/src/main/java/org/pkwmtt/mail/EmailService.java +++ b/src/main/java/org/pkwmtt/mail/EmailService.java @@ -1,10 +1,13 @@ package org.pkwmtt.mail; +import jakarta.annotation.PostConstruct; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; +import org.pkwmtt.exceptions.MailServiceNotAvailableException; +import org.pkwmtt.mail.config.MailConfig; import org.pkwmtt.mail.dto.MailDTO; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; @@ -12,13 +15,23 @@ @RequiredArgsConstructor @Service public class EmailService { + private final Environment environment; private final JavaMailSender mailSender; - @Value("${spring.mail.username}") private String hostEmail; - public void send (MailDTO mail) throws MessagingException { + @PostConstruct + private void assignProperties () { + hostEmail = environment.getProperty("spring.mail.username"); + } + + public void send (MailDTO mail) throws MessagingException, MailServiceNotAvailableException { + if (!MailConfig.isEnabled()) { + throw new MailServiceNotAvailableException(); + } + + MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); diff --git a/src/main/java/org/pkwmtt/mail/EmailTempController.java b/src/main/java/org/pkwmtt/mail/EmailTempController.java index 9898a23..1048a19 100644 --- a/src/main/java/org/pkwmtt/mail/EmailTempController.java +++ b/src/main/java/org/pkwmtt/mail/EmailTempController.java @@ -2,11 +2,12 @@ import jakarta.mail.MessagingException; import lombok.RequiredArgsConstructor; +import org.pkwmtt.exceptions.MailServiceNotAvailableException; +import org.pkwmtt.exceptions.dto.ErrorResponseDTO; import org.pkwmtt.mail.dto.MailDTO; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @@ -17,10 +18,18 @@ public class EmailTempController { @PostMapping public void sendMail (@RequestParam(name = "r") String recipientEmailAddress) - throws MessagingException { + throws MessagingException, MailServiceNotAvailableException { service.send(new MailDTO() .setRecipient(recipientEmailAddress) .setDescription("TEST") .setTitle("TEST")); } + + @ExceptionHandler(MailServiceNotAvailableException.class) + public ResponseEntity handle (Exception e) { + return new ResponseEntity<>( + new ErrorResponseDTO(e.getMessage()), + HttpStatus.SERVICE_UNAVAILABLE + ); + } } diff --git a/src/main/java/org/pkwmtt/mail/config/MailConfig.java b/src/main/java/org/pkwmtt/mail/config/MailConfig.java index 618dc08..595d744 100644 --- a/src/main/java/org/pkwmtt/mail/config/MailConfig.java +++ b/src/main/java/org/pkwmtt/mail/config/MailConfig.java @@ -1,25 +1,46 @@ package org.pkwmtt.mail.config; -import org.springframework.beans.factory.annotation.Value; +import jakarta.annotation.PostConstruct; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import java.util.Properties; @Configuration +@RequiredArgsConstructor public class MailConfig { - @Value("${spring.mail.username}") + @Getter + private static boolean enabled = true; + + private final Environment environment; + private String username; - @Value("${spring.mail.password}") private String password; + @PostConstruct + private void assignAndValidateProperties () { + username = environment.getProperty("spring.mail.username"); + password = environment.getProperty("spring.mail.password"); + + if (username == null || password == null || username.isEmpty() || password.isEmpty()) { + enabled = false; + } + } + @Bean public JavaMailSender javaMailSender () { - JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + + if (!enabled) { + return mailSender; + } + mailSender.setHost("smtp.gmail.com"); mailSender.setPort(587); mailSender.setUsername(username); @@ -32,4 +53,5 @@ public JavaMailSender javaMailSender () { return mailSender; } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index af7d7de..a227ab6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,7 +23,7 @@ logging.level.WireMock.my-mock=off spring.mail.host=smtp.gmail.com spring.mail.port=587 -spring.mail.username=${EMAIL_USERNAME} -spring.mail.password=${EMAIL_PASSWORD} +spring.mail.username=${EMAIL_USERNAME:} +spring.mail.password=${EMAIL_PASSWORD:} spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true From 9f247bc9f2f67a4605ddf743fe53a7e5d3c6e077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Florczak?= <84631301+florczaq@users.noreply.github.com> Date: Sat, 16 Aug 2025 16:59:03 +0200 Subject: [PATCH 8/8] Create status checker endpoint for service condition --- .../pkwmtt/status/DatabaseStatusChecker.java | 26 ++++++ .../status/SystemStatusCheckerService.java | 47 ++++++++++ .../pkwmtt/status/SystemStatusController.java | 20 ++++ .../timetable/TimetableCacheService.java | 93 +++++++++++-------- .../pkwmtt/timetable/TimetableService.java | 29 ++++-- 5 files changed, 166 insertions(+), 49 deletions(-) create mode 100644 src/main/java/org/pkwmtt/status/DatabaseStatusChecker.java create mode 100644 src/main/java/org/pkwmtt/status/SystemStatusCheckerService.java create mode 100644 src/main/java/org/pkwmtt/status/SystemStatusController.java diff --git a/src/main/java/org/pkwmtt/status/DatabaseStatusChecker.java b/src/main/java/org/pkwmtt/status/DatabaseStatusChecker.java new file mode 100644 index 0000000..6af41a8 --- /dev/null +++ b/src/main/java/org/pkwmtt/status/DatabaseStatusChecker.java @@ -0,0 +1,26 @@ +package org.pkwmtt.status; + + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.sql.DataSource; +import java.sql.SQLException; + +@Slf4j +@Service +public class DatabaseStatusChecker { + @Getter + private static boolean enabled = false; + + @Autowired + DatabaseStatusChecker (DataSource dataSource) { + try { + enabled = dataSource.getConnection().isValid(2); + } catch (SQLException e) { + log.error("Couldn't check database connection. Service will be unavailable"); + } + } +} diff --git a/src/main/java/org/pkwmtt/status/SystemStatusCheckerService.java b/src/main/java/org/pkwmtt/status/SystemStatusCheckerService.java new file mode 100644 index 0000000..e7a4731 --- /dev/null +++ b/src/main/java/org/pkwmtt/status/SystemStatusCheckerService.java @@ -0,0 +1,47 @@ +package org.pkwmtt.status; + +import jakarta.annotation.PostConstruct; +import org.pkwmtt.mail.config.MailConfig; +import org.pkwmtt.timetable.TimetableCacheService; +import org.pkwmtt.timetable.TimetableService; +import org.springframework.stereotype.Service; + + +@Service +public class SystemStatusCheckerService { + + private String mailingStatus; + private String databaseStatus; + private String cacheStatus; + private String timetableStatus; + + SystemStatusCheckerService () { + checkStatuses(); + } + + @PostConstruct + private void checkStatuses () { + mailingStatus = assignStatus(MailConfig.isEnabled()); + databaseStatus = assignStatus(DatabaseStatusChecker.isEnabled()); + timetableStatus = assignStatus(TimetableService.isEnabled()); + cacheStatus = assignStatus(TimetableCacheService.isCacheAvailable()); + } + + public String getStatus () { + return String.format( + """ + Server: ✅; + Services: + Mail: %s + Database: %s, + Timetable: %s, + Cache: %s + """, mailingStatus, databaseStatus, timetableStatus, cacheStatus + ); + } + + + private String assignStatus (boolean condition) { + return condition ? "✅" : "❌"; + } +} diff --git a/src/main/java/org/pkwmtt/status/SystemStatusController.java b/src/main/java/org/pkwmtt/status/SystemStatusController.java new file mode 100644 index 0000000..dd055c1 --- /dev/null +++ b/src/main/java/org/pkwmtt/status/SystemStatusController.java @@ -0,0 +1,20 @@ +package org.pkwmtt.status; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/pkwmtt/system/status") +@RequiredArgsConstructor +public class SystemStatusController { + private final SystemStatusCheckerService service; + + @GetMapping + public ResponseEntity getSystemStatus () { + return ResponseEntity.ok(service.getStatus()); + } + +} diff --git a/src/main/java/org/pkwmtt/timetable/TimetableCacheService.java b/src/main/java/org/pkwmtt/timetable/TimetableCacheService.java index 09ad1d1..6bd4861 100644 --- a/src/main/java/org/pkwmtt/timetable/TimetableCacheService.java +++ b/src/main/java/org/pkwmtt/timetable/TimetableCacheService.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Getter; import org.jsoup.Jsoup; import org.pkwmtt.exceptions.SpecifiedGeneralGroupDoesntExistsException; import org.pkwmtt.exceptions.WebPageContentNotAvailableException; @@ -23,23 +24,37 @@ public class TimetableCacheService { private final TimetableParserService parser; private final ObjectMapper mapper; - private final Cache cache; - + + @Getter + private static boolean cacheAvailable = true; + @Value("${main.url:https://podzial.mech.pk.edu.pl/stacjonarne/html/}") private String mainUrl; - - public TimetableCacheService (TimetableParserService parser, ObjectMapper mapper, CacheManager cacheManager) - throws IllegalAccessException { + + public TimetableCacheService (TimetableParserService parser, ObjectMapper mapper, CacheManager cacheManager) { this.parser = parser; this.mapper = mapper; cache = cacheManager.getCache("timetables"); - + if (isNull(cache)) { - throw new IllegalAccessException("Cache [timetables] not configured"); + cacheAvailable = false; } } - + + /** + * @return connection status + */ + public static boolean isConnectionAvailable () { + try { + fetchData("https://podzial.mech.pk.edu.pl/stacjonarne/html/"); + return true; + } catch (Exception e) { + System.out.println(e.getMessage()); + return false; + } + } + /** * Fetches and parses the full timetable for a general group. * @@ -48,32 +63,30 @@ public TimetableCacheService (TimetableParserService parser, ObjectMapper mapper * @throws WebPageContentNotAvailableException if remote content is unavailable */ public TimetableDTO getGeneralGroupSchedule (String generalGroupName) - throws WebPageContentNotAvailableException, SpecifiedGeneralGroupDoesntExistsException { + throws WebPageContentNotAvailableException, SpecifiedGeneralGroupDoesntExistsException { var generalGroupList = getGeneralGroupsMap(); - + if (!generalGroupList.containsKey(generalGroupName)) { throw new SpecifiedGeneralGroupDoesntExistsException(generalGroupName); } - + String groupUrl = generalGroupList.get(generalGroupName); String url = mainUrl + groupUrl; String cacheKey = "timetable_" + generalGroupName; var html = fetchData(url); String json = cache.get( - cacheKey, - () -> { - var timetableDTO =new TimetableDTO( - generalGroupName, - parser.parse(html)); - return mapper.writeValueAsString(timetableDTO); - } + cacheKey, () -> { + var timetableDTO = new TimetableDTO(generalGroupName, parser.parse(html)); + return mapper.writeValueAsString(timetableDTO); + } ); - + return getMappedValue( - json, cacheKey, cache, new TypeReference<>() {} + json, cacheKey, cache, new TypeReference<>() { + } ); } - + /** * Retrieves a mapping of general group names to their corresponding timetable URLs. * @@ -84,40 +97,40 @@ public Map getGeneralGroupsMap () throws WebPageContentNotAvaila var url = mainUrl + "lista.html"; var html = fetchData(url); String json = cache.get( - "generalGroupMap", - () -> mapper.writeValueAsString(parser.parseGeneralGroups(html)) + "generalGroupMap", + () -> mapper.writeValueAsString(parser.parseGeneralGroups(html)) ); - + return getMappedValue( - json, "generalGroupList", cache, new TypeReference<>() { - } + json, "generalGroupList", cache, new TypeReference<>() { + } ); } - + /** * Retrieves the standard list of hour ranges used in the timetable. * * @return list of hour labels (e.g., 08:00–09:30) * @throws WebPageContentNotAvailableException if hour definition page can't be loaded */ - public List getListOfHours () throws WebPageContentNotAvailableException { + public List getListOfHours () throws WebPageContentNotAvailableException { String url = mainUrl + "plany/o25.html"; String json = cache.get( - "hourList", - () -> mapper.writeValueAsString(parser.parseHours(fetchData(url))) + "hourList", + () -> mapper.writeValueAsString(parser.parseHours(fetchData(url))) ); - + List result = getMappedValue( - json, "hourList", cache, new TypeReference<>() { - } + json, "hourList", cache, new TypeReference<>() { + } ); - + //Delete useless spaces result = result.stream().map(item -> item.replaceAll(" ", "")).toList(); - + return result; } - + /** * @param json - json representation of java object * @param key - cache key @@ -128,7 +141,7 @@ public List getListOfHours () throws WebPageContentNotAvailableExceptio * @throws WebPageContentNotAvailableException if there were trouble with fetching data */ private T getMappedValue (String json, String key, Cache cache, TypeReference targetClass) - throws WebPageContentNotAvailableException { + throws WebPageContentNotAvailableException { try { return mapper.readValue(json, targetClass); } catch (JsonProcessingException e) { @@ -136,18 +149,18 @@ private T getMappedValue (String json, String key, Cache cache, TypeReferenc throw new WebPageContentNotAvailableException(); } } - + /** * @param url - url of webpage * @return html code of selected webpage * @throws WebPageContentNotAvailableException if there were trouble with fetching data */ - private String fetchData (String url) throws WebPageContentNotAvailableException { + private static String fetchData (String url) throws WebPageContentNotAvailableException { try { return Jsoup.connect(url).get().html(); } catch (IOException ioe) { throw new WebPageContentNotAvailableException(); } } - + } diff --git a/src/main/java/org/pkwmtt/timetable/TimetableService.java b/src/main/java/org/pkwmtt/timetable/TimetableService.java index c0e6ca3..849cd66 100644 --- a/src/main/java/org/pkwmtt/timetable/TimetableService.java +++ b/src/main/java/org/pkwmtt/timetable/TimetableService.java @@ -2,26 +2,36 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.pkwmtt.exceptions.SpecifiedGeneralGroupDoesntExistsException; import org.pkwmtt.exceptions.SpecifiedSubGroupDoesntExistsException; import org.pkwmtt.exceptions.WebPageContentNotAvailableException; import org.pkwmtt.timetable.dto.DayOfWeekDTO; import org.pkwmtt.timetable.dto.TimetableDTO; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @Slf4j @Service -@RequiredArgsConstructor public class TimetableService { private final TimetableCacheService cachedService; + @Getter + private static final boolean enabled = TimetableCacheService.isConnectionAvailable(); + + @Autowired + TimetableService (TimetableCacheService cachedService) { + this.cachedService = cachedService; + } + /** * Parses the timetable JSON to extract subgroup identifiers like K01, P03, GL04 using regex. * @@ -57,9 +67,7 @@ public List getAvailableSubGroups (String generalGroupName) matchedGroups.add(text); } - return matchedGroups.stream() - .sorted() - .toList(); + return matchedGroups.stream().sorted().toList(); } @@ -103,9 +111,12 @@ public TimetableDTO getFilteredGeneralGroupSchedule (String generalGroupName, Li * @return List of general group's names */ public List getGeneralGroupList () throws WebPageContentNotAvailableException { - return cachedService.getGeneralGroupsMap().keySet().stream() - .sorted() - .collect(Collectors.toList()); + return cachedService + .getGeneralGroupsMap() + .keySet() + .stream() + .sorted() + .collect(Collectors.toList()); } }