spring-projects-experimental / spring-boot-migrator Goto Github PK
View Code? Open in Web Editor NEWSpring Boot Migrator (SBM) is a tool for automated code migrations to upgrade or migrate to Spring Boot
License: Apache License 2.0
Spring Boot Migrator (SBM) is a tool for automated code migrations to upgrade or migrate to Spring Boot
License: Apache License 2.0
All possible attributes for stateless session bean declarations given in an EJB deployment descriptor (ejb-jar.xml
) must be migrated to annotations when migrate-ejb-jar-deployment-descriptor
is applied.
Currently, only beanName
attribute is migrated.
If an ejb-jar.xml
contains additional attributes these are not migrated and the migration is broken/incomplete.
See MigrateEjbDeploymentDescriptor.handleStatelessSessionBean()
A Spring integration test should be created for HTTP endpoints found in the scanned application.
The solution should be generic enough to generate tests not only for Spring Controller but also for e.g. Mule HTTP components.
/info panel
Given precondition
When action
Then result
Rework the flow of scanning, precondition check, and parsing in ScanShellCommand
.
The project should be scanned only once.
Currently, the given project is scanned twice. Once for the precondition check and again inside ScanCommand
.
Provide method buildFile.hasDependencyMatchingRegex()
which considers transitive dependencies too as counterpart to buildFile.hasDeclaredDependencyMatchingRegex()
hasDependencyMatchingRegex
Given pom.xml
contains a dependency that brings a transitive dependency
When hasDependencyMatchingRegex(<regex for the transitive dependency>)
is called on this BuildFile
Then this method should return true
Given pom.xml
contains a dependency that brings a transitive dependency
When hasDependencyMatchingRegex(<regex for the declared dependency>)
is called on this BuildFile
Then this method should return true
hasDeclaredDependencyMatchingRegex
Given pom.xml
contains a dependency that brings a transitive dependency
When hasDeclaredDependencyMatchingRegex(<regex for the transitive dependency>)
is called on this BuildFile
Then this method should return false
Given pom.xml
contains a dependency that brings a transitive dependency
When hasDeclaredDependencyMatchingRegex(<regex for the declared dependency>)
is called on this BuildFile
Then this method should return true
See MigrateWlsEjbDeploymentDescriptor.incorporateIntoSourceFile():69
Replace all usages of org.springframework.sbm.project.parser.Resource
with org.springframework.core.io.Resource
.
Remove mapping and declaration of org.springframework.sbm.project.parser.Resource
The MavenProjectParser
uses a custom Resource
implementation.
In ProjectContextInitializer
the custom Resource
gets mapped to a Spring Resource
.
This is a relict and can be removed so only Spring Resource
is used.
Refactor ProjectContextInitializer
to not create a git repo if none exist.
Throw an Exception instead.
A missing .git
with gitSupportEnabled
will be detected by precondition check.
labels: ["in: mule-3.9"]
Currently, DWL transformations are translated as below
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
(flowVars.someVar splitBy ",") map ("'" ++ $ ++ "'") joinBy ","]]></dw:set-payload>
</dw:transform-message>
@Bean
IntegrationFlow transform() {
return IntegrationFlows.from(...)
...
.transform(TransformClass::transform)
...
.get();
}
class TransformClass {
/** contents of DWL transformation will be pasted as comments*/
public static TransformClass transform(Object payload) {
}
}
If you look at the above TransformClass
there is only access to payload not headers
We need provision to access both headers and payload whilst transformation.
In mule transformations, there will be instances where we need to access headers and payload whilst performing translations. This is evident from client applications that we have encountered where this pattern is used prolifically.
Possible solution can be found here.
Depends-on #62
Provide a recipe to migrate a simple EJB 2.1 to Spring Boot.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_1" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">
<description>Example of a session bean</description>
<display-name>MyTimeBeanEJBName</display-name>
<enterprise-beans>
<session id="Session_MyTime">
<description>An EJB named MyTimeBean</description>
<display-name>MyTimeBeanName</display-name>
<ejb-name>TheTimeBean</ejb-name>
<local-home>mytimepak.MyTimeLocalHome</local-home>
<local>mytimepak.MyTimeLocal</local>
<ejb-class>mytimepak.MyTimeBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
package mytimepak;
public class MyTimeBean implements javax.ejb.SessionBean {
public void ejbCreate() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(javax.ejb.SessionContext ctx) {}
public void unsetSessionContext() {}
public void ejbRemove() {}
public String getTime() {
String s = new java.util.Date().toString();
return s;
}
}
package mytimepak;
import ...springframework..Service;
import ...springframework..Transactional;
/**
* An EJB named MyTimeBean
*/
@Service("TheTimeBean")
@Transactional
public class MyTimeBean {
public String getTime() {
String s = new java.util.Date().toString();
return s;
}
}
Thanks for reporting @Turbots!
Describe the bug
Some recipes of the Spring Boot 2.4 to 2.5 Upgrade functionality are always shown as applicable.
To Reproduce
demo-upgrade-spring-boot-report
demo and upgrade the demo app to 2.5.xExpected behavior
The 2.4 upgrade-related recipes should not be shown for any Spring Boot application with a version different from 2.4.x.
Additional context
For multiple of these recipes the condition is set to org.springframework.sbm.common.migration.conditions.TrueCondition
which makes SBM always show it as applicable.
Make Maven artifact cache configurable by setting an application property.
new MavenArtifactDownloader(
ReadOnlyLocalMavenArtifactCache.mavenLocal().orElse(
new LocalMavenArtifactCache(Paths.get(System.getProperty("user.home"), ".rewrite", "cache", "artifacts")
new MavenArtifactDownloader(new LocalMavenArtifactCache(Paths.get(System.getProperty("user.home"), ".m2", "repository")), ...
It can be useful (and easier to understand) if all dependencies are stored and retrieved from the local Maven repository but then SBM potentially overwrites dependencies in the local Maven repository.
Allow a user to choose.
See DependencyHelper.downloadArtifacts(...)
for artifact configuration and ApplicationProperties
for properties
Verify SBM works with Windows.
C:\my-project\dir
When using SBM under windows it complains about the exclude pattern **/.git/**
.
Providing .git
as pattern on startup succeeded.
Add support for <db:select />
/info panel
Given
Mule xmls are detected
When
<db:select /> component is used
Then
Translate it to Equivalent Spring Integration DSL
Example:
Detects:
<db:select config-ref="Oracle_Configuration" doc:name="Database" fetchSize="500" maxRows="500">
<db:dynamic-query><![CDATA[SELECT * from students]]></db:dynamic-query>
</db:select>
DSL Translation:
.handle((p, h) -> jdbcTemplate.queryForList("SELECT * from students limit 500"))
If boot-2.4-2.5-sql-init-properties
gets applied after boot-2.4-2.5-datasource-initializer
the properties used in the DataSourceInitializerConfiguration
(spring.datasource.schema-...
) get changed. This is wrong.
To avoid this probably easiest is to change property names in DataSourceInitializerConfiguration
, e.g. to spring.sql.init.schema-username
and -password
respectively.
Originally posted by @fabapp2 in #133 (comment)
Describe the bug
When migrating from JAX-RS to Spring inner class HttpStatus.Series
is imported but not used everywhere.
Series custom = HttpStatus.Series.resolve(code);
could be Series custom = Series.resolve(code);
instead.
To Reproduce
Steps to reproduce the behavior:
HttpStatus.Series
with Series
in expected code of ResponseStatusFamilyTest.enumConstantsTest()
Expected behavior
Inner classes are used when imported
Provide a recipe to convert an application from using SpringFox to using SpringDoc.
SpringFox is an often used library to document Spring API's, that has not kept up with recent Spring releases. That prevents users from upgrading their Spring Boot applications.
SpringDoc is an alternative or even successor, which has nicely documented the steps to take for a partial migration.
/info panel
Given an application using springfox
When the springfox-to-springdoc recipe is applied
Then the application uses springdoc
/info panel
Given precondition
When action
Then result
Provide better handling in JavaSourceSetImpl
when adding a JavaSource which doesn't compile.
List<J.CompilationUnit> compilationUnits = javaParser.parse(sourceCode);
J.CompilationUnit parsedCompilationUnit = compilationUnits.get(0);
Verify that compilationUnits
is not empty/null
The error message when compilationUnits
is empty, because compilation failed)
/info panel
Given a user adds a new Java source file through JavaSourceSetImpl
When the source code doesn't compile and the list of compilation units is empty
Then the stacktrace should provide more precise information about what went wrong
A set of preconditions should be run at the beginning of a scan to warn the user about
potential problems when scanning an application that does not fulfill requirements.
For a better UX a user should be warned about expected problems when scanning (but before applying recipes) an application that does not fulfill given preconditions.
Given A user scans an application that does not fulfill one or more preconditions +
When SBM performs a precondition check that fails +
Then A warning is shown to the user and the scan is cancelled.
Precondition | Warning |
---|---|
No pom.xml found |
SBM requires a Maven build file. Please provide a minimal pom.xml. |
no dir src/main/java exists |
Precondition check could not find a src/main/java dir. This dir is required. |
Git-Support is enabled but no .git exists |
Git-Support is enabled but the scanned project is not under git. |
Multiple modules found | Maven reactor support is experimental and not fully supported. |
Thanks @virgium03 for raising this issue!
Version: 0.9.1
.
If any of the pom.xml
files in a project contain empty properties
elements, the tool fails. The fix is to remove the empty properties
element from the incriminated pom.xml
file.
Examples which generate a failure:
<properties> </properties>
or
<properties>
</properties>
The stacktrace is as follows:
java.io.UncheckedIOException: Failed to parse C:\Users\ratoico\work\projects\uumds-admin\admin-common\common-facade\pom.xml
at org.openrewrite.maven.internal.RawMaven.parse(RawMaven.java:90)
at org.openrewrite.maven.MavenParser.lambda$parseInputs$0(MavenParser.java:74)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.openrewrite.maven.MavenParser.parseInputs(MavenParser.java:75)
at com.vmware.sbm.project.buildfile.RewriteMavenParser.parseInputs(RewriteMavenParser.java:46)
at org.openrewrite.Parser.parse(Parser.java:39)
at com.vmware.sbm.project.buildfile.OpenRewriteMavenBuildFilesFactory.applyProjections(OpenRewriteMavenBuildFilesFactory.java:32)
at com.vmware.sbm.project.SimpleProjectContextBuilder.buildContext(SimpleProjectContextBuilder.java:43)
at com.vmware.sbm.project.CachingProjectContextBuilder.buildContext(CachingProjectContextBuilder.java:43)
at com.vmware.sbm.commands.ScanCommand.execute(ScanCommand.java:26)
at com.vmware.sbm.shell.ScanShellCommand.scan(ScanShellCommand.java:39)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.shell.Shell.evaluate(Shell.java:180)
at org.springframework.shell.Shell.run(Shell.java:142)
at org.springframework.shell.jline.InteractiveShellApplicationRunner.run(InteractiveShellApplicationRunner.java:84)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:787)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at com.vmware.sbm.SpringShellApplication.main(SpringShellApplication.java:10)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("") to element ofjava.util.LinkedHashMap<java.lang.String,java.lang.String>
(but could if coercion was enabled usingCoercionConfig
)
at [Source: (sun.nio.ch.ChannelInputStream); line: 17, column: 5] (through reference chain: org.openrewrite.maven.internal.RawPom["properties"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadCoercion(DeserializationContext.java:1666)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._checkCoercionFail(StdDeserializer.java:1432)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromEmptyString(StdDeserializer.java:325)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:444)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3585)
at org.openrewrite.maven.internal.RawMaven.parse(RawMaven.java:84)
... 38 more
MavenProjectParser
, see https://github.com/openrewrite/rewrite-maven-plugin/blob/main/src/main/java/org/openrewrite/maven/MavenMojoProjectParser.java
and code providedConfigure build GitHub action to cache dependencies
To speed up build
Describe the bug
When migrating JAX-RS to Spring @RestController
calls to Response
are replaced with calls to ResponseEntity
and the build()
call is kept. This method is not defined in ResponseEntity
and must be replaced.
To Reproduce
Steps to reproduce the behavior:
.build()
in expected output of ResponseEntityReplacementTest.testReplaceOkWithBody()
Expected behavior
The migrated Spring code has no call to ResponseEntity.build()
Additional context
More occurrences marked with // FIXME: #115
Provide a demo for recipe 'cn-spring-cloud-config-server'.
labels: ["good first issue","in: JEE","to_archive"]
The shell should allow the user to toggle the sbm.gitSupportEnabled
flag.
When trying SBM it can be annoying to scan projects not under git as the precondition check will complain that the flag is true but the application is not under git.
This would allow a user to just turn git support off without leaving the Shell.
Given sbm.gitSupportEnabled
is true
When calling set-property sbm.gitSupportEnabled false
in shell
Then get-property sbm.gitSupportEnabled
should return false
Given sbm.gitSupportEnabled
is false
When calling set-property sbm.gitSupportEnabled true
in shell
Then get-property sbm.gitSupportEnabled
should return true
Currently, the integration test BootifySimpleMuleAppIntegrationTest
uses ibmcom/mq
which does not support ARM architecture. To mediate this the integration test is ignored on Mac M1 (ARM) for now.
The integration test should run on all architectures.
The dockerhub repo says the image is not maintained anymore and images should be retrieved from IBM image repo.
See https://hub.docker.com/r/ibmcom/mq.
Thanks @virgium03 for raising this issue!
Version: 0.9.1
Have a multi-module Maven project like this, where project B
inherits from the project A
pom.xml
file:
A
├── pom.xml
├── B
├── pom.xml
If project B
(child) has a Maven dependency defined like this:
<dependency>
<groupId>a.b.c</groupId>
<artifactId>xyz</artifactId>
<version>1.0</version>
<optional>${boolean-variable}</optional>
</dependency>
and project A
(parent) has the boolean.variable
defined as a property like so:
<properties>
<boolean-variable>true</boolean-variable>
</properties>
the scanning fails like this:
java.io.UncheckedIOException: Failed to parse ${project.path}\pom.xml
at org.openrewrite.maven.internal.RawMaven.parse(RawMaven.java:90)
at org.openrewrite.maven.MavenParser.lambda$parseInputs$0(MavenParser.java:74)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.openrewrite.maven.MavenParser.parseInputs(MavenParser.java:75)
at com.vmware.sbm.project.buildfile.RewriteMavenParser.parseInputs(RewriteMavenParser.java:46)
at org.openrewrite.Parser.parse(Parser.java:39)
at com.vmware.sbm.project.buildfile.OpenRewriteMavenBuildFilesFactory.applyProjections(OpenRewriteMavenBuildFilesFactory.java:32)
at com.vmware.sbm.project.SimpleProjectContextBuilder.buildContext(SimpleProjectContextBuilder.java:43)
at com.vmware.sbm.project.CachingProjectContextBuilder.buildContext(CachingProjectContextBuilder.java:43)
at com.vmware.sbm.commands.ScanCommand.execute(ScanCommand.java:26)
at com.vmware.sbm.shell.ScanShellCommand.scan(ScanShellCommand.java:39)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.shell.Shell.evaluate(Shell.java:180)
at org.springframework.shell.Shell.run(Shell.java:142)
at org.springframework.shell.jline.InteractiveShellApplicationRunner.run(InteractiveShellApplicationRunner.java:84)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:787)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at com.vmware.sbm.SpringShellApplication.main(SpringShellApplication.java:10)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of typejava.lang.Boolean
from String "${boolean-variable}": only "true" or "false" recognized
at [Source: (sun.nio.ch.ChannelInputStream); line: 247, column: 44] (through reference chain: org.openrewrite.maven.internal.RawPom["dependencies"]->org.openrewrite.maven.internal.RawPom$Dependencies["dependency"]->java.util.ArrayList[33]->org.openrewrite.maven.internal.RawPom$Dependency["optional"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1851)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:1079)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseBoolean(StdDeserializer.java:552)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer.deserialize(NumberDeserializers.java:227)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer.deserialize(NumberDeserializers.java:200)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:347)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:114)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3585)
at org.openrewrite.maven.internal.RawMaven.parse(RawMaven.java:
Contents of .gitignore
should be ignored when scanning a given application with PathScanner
.
Some resources and dirs (like target
) are ignored by default, this can be configured by setting sbm.ignoredPathsPatterns
. But all ignored resources in .gitignore
should also be ignored.
Given the project to migrate contains a resource some-file.txt
When the .gitgnore
contains some-file.txt
Then PathScanner.scan(Path)
should not return the ignored resource(s)
It must handle all kinds of ignore patterns from .gitignore
.
See sbm.ignoredPathsPatterns
in components/sbm-core/src/main/resources/application-core.properties
See PathScanner
Log messages on info/warn/error level should be routed to the shell output with a similar (no) formatting as other printouts in the shell.
Log statements printed by default Console logback adapter look very different from the output printed by RecipeProgressRenderer
.
To make log statements look like other printouts the log messages should be retrieved by a custom Appender and the default console appender needs to be deactivated.
Given During a running Action
When log.info(...)
gets called
Then the message should be printed to the user as [ok] <message>
Given During a running Action
When log.warn(...)
gets called
Then the message should be printed to the user as [!] <message>
with [!]
in yellow/orange
Given During a running Action
When log.error(...)
gets called
Then the message should be printed to the user as [X] <message>
with [X]
in red
The first (maybe naive) attempt worked for loggers retrieved through a call to LoggerFactory but failed with logger retrieved using lombok's @Slf4J
annotation.
The re-routing of Logback log messages fails in unit test (RecipeProgressRendererTest) when ran in combination with other integration tests. Guessing that the combination with lombok @slf4j is the issue. Commented out the code that starts the re-routing.
Fix and enable test in AddNewDependencyTest
.
Before removing an EJB definition section from ejb-jar.xml
it must be verified that all information was migrated. Currently, the EJB definition is removed right away.
Remove or comment out all migrated properties and only remove the EJB definition if no properties exist.
As long as not everything is guaranteed to be migrated from an ejb-jar.xml
deployment descriptor it must be verified that all existing information has been migrated before removing the information.
Otherwise, information might be lost and the migration would be incomplete/broken.
Given migrate-ejb-jar-deployment-descriptor
is applied
When ejb-jar.xml
contains handled and unhandled elements
Then the user must understand what has been automatically migrated and what needs to be migrated manually
See MigrateEjbDeploymentDescriptor:41
(Action)
See MigrateEjbJarDeploymentDescriptorRecipe
(Recipe)
Describe the bug
A flow with a Dataweave transformation will result in creation of a transformation class whose name is dependent on flow name.
When a flow contains multiple dataweave transformation, it should produce multiple classes, right now it is producing only one class for multiple dataweave transformations.
To Reproduce
Steps to reproduce the behavior:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd">
<flow name="multipleTransforms">
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json indent = true, skipNullOn = "everywhere"
---
{
"hello": {
"world": {
"hello": "indeed!",
},
}
}]]></dw:set-payload>
</dw:transform-message>
<logger />
<dw:transform-message doc:name="Build Response Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json indent = true, skipNullOn = "everywhere"
---
{
"responseBody": {
"responseInfo": {
"responseStatus": "200"
},
}
}]]></dw:set-payload>
</dw:transform-message>
</flow>
</mule>
MultipleTransformsTransform
Expected behavior
Since there are two DWL transforms, this should produce two distinct transform files, may be MultipleTransformsTransform_1
and MultipleTransformsTransform_2
HTTP Listener annotated with @WebListener
should be handled by migrate-annotated-servlets
recipe.
While looking at the code this should be the case already (the annotation has package javax.servlet.*
.
Implement a new / extend an existing test to verify that event listener annotated with @WebListener
are available in the migrated Spring Boot application.
@WebListener
works similar to @WebServlet
but it's not tested (and might require enhancing of the recipe).
Given A JEE application has a event listener annotated with @WebListener
When migrate-annotated-servlets
is applied
Then The migrated Spring Application must recognize and initialize the WebListener
Would adding a tool like Dependabot or Renovate be an option for this project? That could eliminate the need to explicitly upgrade dependencies by hand.. Looking through the list both of these properties are outdated:
<openrewrite.version>7.16.3</openrewrite.version>
<openrewrite.spring.version>4.14.1</openrewrite.spring.version>
The most recent versions as of writing are:
<openrewrite.version>7.19.0</openrewrite.version>
<openrewrite.spring.version>4.17.0</openrewrite.spring.version>
Originally posted by @timtebeek in #7 (comment)
Describe the bug
The demo for Spring Boot upgrades is not working because it uses fixed paths
To Reproduce
Run the demo ;)
EjbJarXml
specialized resource should unmarshal ejb-jar.xml
deployment descriptor for EJB 2.1.
Given The scanned application contains this ejb-jar.xml
deployment descriptor
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_2_1.xsd" version="2.1">
<description>Example of a session bean</description>
<display-name>MyTimeBeanEJBName</display-name>
<enterprise-beans>
<session id="Session_MyTime">
<description>An EJB named MyTimeBean</description>
<display-name>MyTimeBeanName</display-name>
<ejb-name>MyTimeBean</ejb-name>
<local-home>mytimepak.MyTimeLocalHome</local-home>
<local>mytimepak.MyTimeLocal</local>
<ejb-class>mytimepak.MyTimeBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
When projectContext.search(new EjbJarXmlResourceFilter()).get().getEjbJarXml()
is called
Then The XML data (e.g. ejb-name) shozdl be accessible through the EjbJarXml
API
When component is detected, translate it to appropriate spring DSL translation
input
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw"
xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<flow name="foreach">
<http:listener config-ref="HTTP_Listener_Configuration" path="/foreach" doc:name="HTTP"/>
<foreach collection="#[['apple', 'banana', 'orange']]">
<logger message="#[payload]" level="INFO" />
</foreach>
<logger message="Done with for looping" level="INFO" />
</flow>
</mule>
output:
@Bean
IntegrationFlow flow() {
return IntegrationFlows.from(Http.inboundGateway("/foreachtest"))
//TODO: translate expression #[['apple', 'banana', 'orange']] which must produces an array
// to iterate over
.split()
.log()
.aggregate()
.log()
.get();
}
Children of foreach can be complex such as choice
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw"
xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<flow name="foreach">
<http:listener config-ref="HTTP_Listener_Configuration" path="/foreach" doc:name="HTTP"/>
<foreach collection="#[[1, 2, 3, 4]]">
<logger message="#[payload]" level="INFO" />
<choice doc:name="Choice">
<when expression="#[payload == 1]">
<logger level="INFO" message="Ondu"></logger>
</when>
<when expression="#[payload == 2]">
<logger level="INFO" message="Eradu"></logger>
</when>
<when expression="#[payload == 3]">
<logger level="INFO" message="Mooru"></logger>
</when>
<otherwise>
<logger level="INFO" message="Moorina mele"></logger>
</otherwise>
</choice>
</foreach>
<logger message="Done with for looping" level="INFO" />
</flow>
</mule>
output
@Bean
IntegrationFlow foreach() {
return IntegrationFlows.from(Http.inboundChannelAdapter("/foreach")).handle((p, h) -> p)
//TODO: translate expression #[[1, 2, 3, 4]] which must produces an array
// to iterate over
.split()
/* TODO: LinkedMultiValueMap might not be apt, substitute with right input type*/
.<LinkedMultiValueMap<String, String>, String>route(
p -> p.getFirst("dataKey") /*TODO: use apt condition*/,
m -> m
.subFlowMapping("dataValue" /*TODO: Translate dataValue to #[payload == 1]*/,
sf -> sf.log(LoggingHandler.Level.INFO, "Ondu")
)
.subFlowMapping("dataValue" /*TODO: Translate dataValue to #[payload == 2]*/,
sf -> sf.log(LoggingHandler.Level.INFO, "Eradu")
)
.subFlowMapping("dataValue" /*TODO: Translate dataValue to #[payload == 3]*/,
sf -> sf.log(LoggingHandler.Level.INFO, "Mooru")
)
.resolutionRequired(false)
.defaultSubFlowMapping(sf -> sf.log(LoggingHandler.Level.INFO, "Moorina mele"))
)
.aggregate()
.log(LoggingHandler.Level.INFO, "Done with for looping")
.get();
}
More information of foreach mule component can be found here
Batch sizing using foreach can be supported later
Depends-on: #52
Investigate, fix and/or close.
See comments // TODO: #486
MoveFilesActionTest
started failing in CI while passing locally.
The file AnotherFile.foo
was moved successfully while the new path for SomeFile.foo
resolved to the path without the filename.
Scanning
app.zip
initialize-spring-boot-migration
as applicable which is wrongdependency-management
section which is wrong as dependencies are managed by parent pom/info panel
Given precondition
When action
Then result
Calculating base packages should return the common parent package, even if it is the default (no) package.
In BasePackageCalculator.calculateBasePackage(List<JavaSource> javaSources)
For e.g. two classes com.acme.some.A
and com.acme.other.B
the current calculation does fail as it does not recognize com.acme
as possible common base package.
Given base package should be calculated for an application
When two classes com.acme.some.A
and com.acme.other.B
exist
Then the returned base package should be com.acme
Given base package should be calculated for an application
When two classes com.acme.some.A
and com.example.other.B
exist
Then the returned base package should be com
Given base package should be calculated for an application
When two classes com.acme.some.A
and org.example.other.B
exist
Then the returned base package should be ""
See JavaSourceSetImplTest.getBasePackageShouldReturnDefaultIfNoDistinctRootPackageExists()
This test should expect com.vmware.sbm
instead of the default base package.
All recipes/actions calculating the base package for Spring components and configurations should check if the returned base package is the default package/empty and handle this situation. At least initialize-spring-boot-migration
would be affected.
For Spring applications to work without one common base package, a @ComponentScan
could be used.
labels: ["type: enhancement","in: mule-3.9"]
When a choice element is embedded inside another choice element we need to translate appropriate spring DSL.
Choice inside a choice is supported by mule, to complete component support we need to do this.
<choice doc:name="Choice">
<when expression="#[flowVars.language == 'Spanish']">
<choice>
<when expression="#[flowVars.sayHello == 'true']">
<set-payload value="Hola!"/>
</when>
<otherwise>
<set-payload value="Adiós"/>
</otherwise>
</choice>
</when>
<when expression="#[flowVars.language == 'French']">
<choice>
<when expression="#[flowVars.sayHello == 'true']">
<set-payload doc:name="Reply in French" value="Bonjour!"/>
</when>
<otherwise>
<set-payload doc:name="Reply in French" value="Au revoir"/>
</otherwise>
</choice>
</when>
<otherwise>
<set-variable variableName="language" value="English" doc:name="Set Language to English"/>
<set-payload doc:name="Reply in English" value="Hello"/>
</otherwise>
</choice>
To be written.
There is already support for Non nested Choice component. One can find the source here and tests here
Describe the bug
Integration tests that use a Docker container fail with Mac M1
To Reproduce
Steps to reproduce the behavior:
BootifyAnnotatedServletsIntegrationTest
Expected behavior
The application builds a Docker container and runs it using testcontainers
Stacktrace
missing compatible architecture (have 'i386,x86_64', need 'arm64e')
12:41:53.485 [main] ERROR o.t.d.DockerClientProviderStrategy - UnixSocketClientProviderStrategy: failed with exception RuntimeException (java.lang.UnsatisfiedLinkError: /private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp: dlopen(/private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp, 0x0001): tried: '/private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp' (fat file, but missing compatible architecture (have 'i386,x86_64', need 'arm64e'))). Root cause UnsatisfiedLinkError (/private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp: dlopen(/private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp, 0x0001): tried: '/private/var/folders/sh/nw78y14d38jb_57ptd_k0jdr0000gq/T/jna-1226527383/jna14683793770511009461.tmp' (fat file, but missing compatible architecture (have 'i386,x86_64', need 'arm64e')))
Environment (please complete the following information):
openjdk version "11.0.14.1" 2022-02-08 LTS
OpenJDK Runtime Environment Zulu11.54+25-CA (build 11.0.14.1+1-LTS)
OpenJDK 64-Bit Server VM Zulu11.54+25-CA (build 11.0.14.1+1-LTS, mixed mode)
Additional context
net.java.dev.jna:jna
< 5.8.0 was brought in by spring-shell-starter and has been excluded.docker run -it docker.io/library/jboss-sample:1.0.0
, but with a warningWARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Spring Shell can support auto completion through a ValueProvider interface.
I image you'd need two separate implementation, each for the respective purpose.
Nice usability improvement.
Given the interactive prompt
When the user types scan (or apply)
And the user presses TAB
Then auto complete suggestions appear
HTTP Listener annotated with @WebFilter
should be handled by migrate-annotated-servlets
recipe.
While looking at the code this should be the case already (the annotation has package javax.servlet.*
.
Implement a new / extend an existing test to verify that web filters annotated with @WebFilter
are available in the migrated Spring Boot application.
@WebFilter
works similar to @WebServlet
but it's not tested (and might require enhancing of the recipe).
Given A JEE application has a event listener annotated with @WebFilter
When migrate-annotated-servlets
is applied
Then The migrated Spring Application must recognize and initialize the WebFilter
Describe the bug
Template error generating HTML report.
freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> recipesFound [in template "upgrade-asciidoc.ftl" at line 46, column 6]
To Reproduce
Steps to reproduce the behavior:
#!/bin/bash
set -e
source "$HOME/.sdkman/bin/sdkman-init.sh"
project='spring-petclinic-sbm'
wget --no-clobber https://github.com/spring-projects-experimental/spring-boot-migrator/releases/download/0.11.0/spring-boot-migrator.jar
git clone [email protected]:spring-projects/spring-petclinic.git $project
cd $project
#git reset --hard
#git clean -f
git checkout 09e07869ac8cea1d08bd62802d5e0dad97827b87 # commit on 2.4.x
cd -
sdk use java 11.0.15-tem
java -jar spring-boot-migrator.jar
Expected behavior
A HTML report, possibly with all steps resolved
Stacktrace
spring-petclinic-sbm:> apply boot-2.4-2.5-upgrade-report
Applying recipe 'boot-2.4-2.5-upgrade-report'
.. Create Upgrade Report for a Spring Boot 2.4 Application16:42:24.213 [main] ERROR freemarker.runtime - Error executing FreeMarker template
freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> recipesFound [in template "upgrade-asciidoc.ftl" at line 46, column 6]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #if recipesFound [in template "upgrade-asciidoc.ftl" at line 46, column 1]
----
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
at freemarker.core.UnexpectedTypeException.newDescriptionBuilder(UnexpectedTypeException.java:85)
at freemarker.core.UnexpectedTypeException.<init>(UnexpectedTypeException.java:48)
at freemarker.core.NonBooleanException.<init>(NonBooleanException.java:47)
at freemarker.core.Expression.modelToBoolean(Expression.java:195)
at freemarker.core.Expression.evalToBoolean(Expression.java:178)
at freemarker.core.Expression.evalToBoolean(Expression.java:163)
at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48)
at freemarker.core.Environment.visit(Environment.java:347)
at freemarker.core.Environment.visit(Environment.java:353)
at freemarker.core.Environment.process(Environment.java:326)
at freemarker.template.Template.process(Template.java:383)
at org.springframework.sbm.boot.upgrade_24_25.actions.Boot_24_25_UpgradeReportAction.renderMarkdown(Boot_24_25_UpgradeReportAction.java:80)
at org.springframework.sbm.boot.upgrade_24_25.actions.Boot_24_25_UpgradeReportAction.apply(Boot_24_25_UpgradeReportAction.java:69)
at org.springframework.sbm.engine.recipe.Action.applyWithStatusEvent(Action.java:37)
at org.springframework.sbm.engine.recipe.Recipe.lambda$apply$2(Recipe.java:97)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.springframework.sbm.engine.recipe.Recipe.apply(Recipe.java:97)
at org.springframework.sbm.engine.commands.ApplyCommand.execute(ApplyCommand.java:70)
at org.springframework.sbm.shell.ApplyShellCommand.apply(ApplyShellCommand.java:54)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.shell.Shell.evaluate(Shell.java:180)
at org.springframework.shell.Shell.run(Shell.java:142)
at org.springframework.shell.jline.InteractiveShellApplicationRunner.run(InteractiveShellApplicationRunner.java:84)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:793)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:346)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1365)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
at org.springframework.sbm.SpringShellApplication.main(SpringShellApplication.java:27)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Action [org.springframework.sbm.boot.upgrade_24_25.actions.Boot_24_25_UpgradeReportAction] with description 'Create Upgrade Report for a Spring Boot 2.4 Application' failed: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> recipesFound [in template "upgrade-asciidoc.ftl" at line 46, column 6]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #if recipesFound [in template "upgrade-asciidoc.ftl" at line 46, column 1]
----
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
Desktop (please complete the following information):
Prepare demo for Mule to Boot migration
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.