Spring Boot 3.2 issues
As part of the LuciadFusion 2024.0 release, the Spring Boot dependencies were upgraded from version 2.7 to 3.2. Consequently, the Spring Framework has been upgraded from version 5.7 to 6.1 and Spring Security has been upgraded from version 5.8 to 6.2. Because these are new major versions, they contain breaking changes. You may run into one of these issues after upgrading from LuciadFusion 2023.x or older to LuciadFusion 2024.x or later.
Jakarta EE
The new Spring version depends on the Jakarta EE 10 specification. As a result, you must upgrade your servlet container to a version that supports Jakarta EE 10, like Tomcat 10.1 or Jetty 12 (packaged with LuciadFusion).
Moreover, this Spring version has changed the root package name of its Java classes from javax
to jakarta
.
If you use any:
-
Jakarta Servlet classes, such as
HttpRequestServlet
-
Jakarta Validation classes, such as the
@Valid
annotation -
Jakarta Dependency Injection, such as the
@Inject
annotation
you must change your imports from the javax
to the jakarta
package.
Unauthorized requests
In Spring Security 5.8 and earlier, requests without an authorization rule were permitted by default. However, denying requests without authorization rules by default puts your application in a stronger security position. In that case, your application requires that authorization rules are clearly defined for every endpoint. Consequently, since Spring Security 6.0, Spring Security denies any request that’s missing an authorization rule by default.
Authorization rules for LuciadFusion Platform Services are applied automatically based on the information returned by
the getEndPointPatterns()
method in ILfnServiceTypeConfiguration
. You may need to override this method if the default implementation
doesn’t give a valid pattern for your custom service types. You can configure the applied authorization rules for all services using the
fusion.security.serviceAuthenticationRequired
. When you set it to true
, authentication will be required for all services. If you set it to false
,
anonymous access to services is allowed. For more fine-grained configuration of access to services, read the
How to configure access to services in LuciadFusion article.
If you configured custom endpoints, you must make sure to add a SecurityFilterChain
with an
authorization rule covering that endpoint.
Otherwise, you’ll get 403 Forbidden
errors when trying to access those endpoints.
Trailing slash URL matching
Spring Boot 3 significantly changed the trailing slash matching configuration option.
This option determines whether to treat a URL with a trailing slash the same as a URL without one.
Previous versions of Spring Boot set this option to true
by default. As a result, a controller
with a GetMapping("/some/greeting")
annotation for example, would match both
GET /some/greeting
and GET /some/greeting/
” by default in previous Spring Boot versions.
In current versions, accessing a URL with a trailing slash, such as GET /some/greeting/
,
results in a 404 error, unless the controller is specifically set up to handle URLs with a trailing slash.
Other Spring issues
If you run into any other Spring issue, check in the Spring migration guides if a Spring Framework change may be causing your issue.
These are the links to the Spring migration guides and release notes:
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2-Release-Notes
-
https://docs.spring.io/spring-security/reference/5.8/migration/index.html
-
https://docs.spring.io/spring-security/reference/6.1/migration/index.html
Spring Boot 2.7 issues
As part of the LuciadFusion 2023.0 release, the Spring Boot dependencies were upgraded from version 2.1 to 2.7. Consequently, the Spring Framework version has been upgraded from version 4.0 to 5.7 and Spring Security has been upgraded from 4.0 to 5.8. Because these are new major versions, they contain breaking changes. You may run into one of these issues after upgrading from LuciadFusion 2022.x or older to LuciadFusion 2023.x or later.
Configuration file processing has changed
Spring Boot 2.4 has changed the way that YAML files are processed.
Because of this, you can no longer use spring.profiles.include
in profile-specific YAML files.
If you only want to import other YAML files and aren’t interested in activating a profile, you can use spring.config.import
as an alternative.
If you do want other profiles activated, you can use the new Profile Groups feature.
For more information, see the Spring Boot Config Data Migration Guide.
Please note that the YAML files provided with LuciadFusion have already been migrated.
This means that it isn’t possible to use the spring.config.use-legacy-processing
property to revert to the legacy way of processing YAML files.
Circular references prohibited by default
Circular reference detection has become stricter. This means that, for example, self-injection is no longer possible.
If your application fails to start due to a BeanCurrentlyInCreationException
, we strongly recommend that you update your configuration to break the dependency cycle.
For more information, see the Spring Boot 2.6 release notes.
Property server.use-forward-headers deprecated
The server.use-forward-headers
property has been deprecated in favor of server.forward-headers-strategy
.
If you were using server.use-forward-headers: true
, then you need to update it to server.forward-headers-strategy: native
.
For more information, see the Spring Boot 2.2 release notes.
Other Spring issues
If you run into any other Spring issue, check in the release notes for the various Spring versions if a Spring Framework change may be causing your issue.
These are the links to the Spring Boot and Spring Framework release notes:
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes
-
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes
-
https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x
-
https://docs.spring.io/spring-security/reference/5.8/whats-new.html
YAML format issues
Do not use tabs, use spaces
A correct indentation in YAML files is really important. Tabs should never be used. A good format
is to use 2 spaces for an indentation level. The following example shows 2 server properties server.servlet.context-path
and server.port
:
server: servlet.context-path: /path port: 8080
Error: Duplicate key
Property keys or parts of property keys cannot be used more than once in the same YAML file.
Wrong:
fusion.security: enabled: true fusion.security.cors.origins: "*" fusion.security: authenticationManager: ldap
The key fusion.security
is encountered twice. The correct use is:
fusion.security: enabled: true cors.origins: "*" authenticationManager: ldap
Issues with properties and Spring profiles
Overwriting properties and spring.config.import
When a property is defined two times in two separate profiles, the value of the property of the rightmost active profile
is taken. For example, when you have -Dspring.profiles.active=fusion.single,custom.profile
, the properties re-defined in
custom.profile
will overwrite the ones defined in fusion.single profile
.
If a property occurs in a profile as well as in its imported configuration file, the property values in the imported configuration file takes precedence.
For example, file fusion.common.yml
configuration file specifies:
fusion.security.enabled: true
File application-fusion.testing.yml
specifies:
spring.config.import: classpath:fusion.common.yml fusion.security.enabled: false
The resulting value of fusion.security.enabled
is true
. From the Spring Javadoc for spring.config.import
:
Imports are processed as they are discovered, and are treated as additional documents inserted immediately below the one that
declares the import.
Disabling authentication
During development, you may not want to log into the LuciadFusion Studio application. Simply setting the
fusion.security.enabled
to false
removes the login step. Every user will automatically be logged in as fusion_guest_user.
Spring Boot Actuator issues
LuciadFusion includes the Spring Boot Actuator module. It enables several handy features to monitor and debug your application through the endpoints it exposes. Those endpoints are secured by default.
A non-exhaustive list of Actuator endpoints:
-
env
: exposes system properties and all properties from Spring’sConfigurableEnvironment
. -
configprops
: displays a collated list of all@ConfigurationProperties
. It allows you to see the resolved property values. -
beans
: displays a complete list of all the Spring beans in your application. -
mappings
: displays a collated list of all exposed endpoints, meaning all@RequestMapping
paths. -
loggers
: shows and modifies the configuration of loggers in the application. -
shutdown
: allows the application to be gracefully shut down. This is not enabled by default. Enable it by setting the propertymanagement.endpoints.shutdown.enabled: true
and adding 'shutdown' to the list of endpoints listed in the propertymanagement.endpoints.web.exposure.include
.
Liquibase could not acquire change log lock
LuciadFusion Studio uses a tool called Liquibase to handle the migration of the database to the new database schema for every new release of LuciadFusion. This tool gets run automatically by Studio at startup.
Liquibase uses a distributed locking system to only allow one process to update the database at a time. The other processes will simply wait until the lock has been released. It is possible that this lock does not get released If the LuciadFusion Studio startup gets interrupted during a Liquibase migration. If this occurs, the next time Studio gets started, it will seem to hang for a long time, after which the following error will be printed on the console.
2018-12-18 18:08:25.675 ERROR 26079 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.luciad.internal.fusion.platform.studio.service.configuration.InstallerConfiguration': Invocation of init method failed; nested exception is org.springframework.context.ApplicationContextException: Failed to create application context; nested exception is liquibase.exception.LockException: Could not acquire change log lock. Currently locked by 148.53.163.85 (148.53.163.85) since 12/18/18 6:02 PM at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1737) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) at com.luciad.fusion.platform.TLfnFusionPlatformApplication.main(TLfnFusionPlatformApplication.java:53) Caused by: org.springframework.context.ApplicationContextException: Failed to create application context; nested exception is liquibase.exception.LockException: Could not acquire change log lock. Currently locked by 148.53.163.85 (148.53.163.85) since 12/18/18 6:02 PM at com.luciad.internal.fusion.platform.studio.service.configuration.InstallerConfiguration.runInstaller(InstallerConfiguration.java:58) at java.util.ArrayList.forEach(ArrayList.java:1257) at com.luciad.internal.fusion.platform.studio.service.configuration.InstallerConfiguration.runInstallers(InstallerConfiguration.java:42) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ... 18 common frames omitted Caused by: liquibase.exception.LockException: Could not acquire change log lock. Currently locked by 148.53.163.85 (148.53.163.85) since 12/18/18 6:02 PM at liquibase.lockservice.StandardLockService.waitForLock(StandardLockService.java:190) at liquibase.Liquibase.update(Liquibase.java:196) at liquibase.Liquibase.update(Liquibase.java:192) at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:431) at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:388) at com.luciad.internal.fusion.platform.studio.service.installers.LiquibaseInstaller.install(LiquibaseInstaller.java:70) at com.luciad.internal.fusion.platform.studio.service.configuration.InstallerConfiguration.runInstaller(InstallerConfiguration.java:53) ... 27 common frames omitted
To resolve this issue, you can release the lock manually by clearing the table fusion_studio_liquibase.databasechangeloglock
in your database.
For more information go to https://docs.liquibase.com/concepts/tracking-tables/databasechangeloglock-table.html.