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.

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.

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’s ConfigurableEnvironment.

  • 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 property management.endpoints.shutdown.enabled: true and adding 'shutdown' to the list of endpoints listed in the property management.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.