skills/code-analysis/spring-mvc-to-boot-migrator/SKILL.md
Migrates a Spring MVC application to Spring Boot, converting XML config to auto-configuration, restructuring the project, and replacing container deployment with embedded. Use when modernizing a legacy Spring app, when moving off a standalone servlet container, or when the user has web.xml and wants application.yml.
npx skillsauth add santosomar/general-secure-coding-agent-skills spring-mvc-to-boot-migratorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Spring Boot is Spring MVC with conventions, embedded server, and auto-configuration. The migration isn't a rewrite — it's deleting XML and letting Boot infer it.
| Concern | Spring MVC (classic) | Spring Boot | Migration effort |
| --------------------- | --------------------------------- | ------------------------------------------ | ---------------- |
| @Controller classes | @Controller, @RequestMapping | Same — unchanged | Zero |
| @Service, @Repository | Same annotations | Same — unchanged | Zero |
| Bean wiring (XML) | <bean id=... class=...> | @Configuration + @Bean, or just @Component | High — this is the work |
| DispatcherServlet setup| web.xml | Auto-configured — delete it | Delete |
| Server | Deploy WAR to Tomcat | Embedded Tomcat — java -jar | pom.xml change |
| Properties | Multiple .properties via <context:property-placeholder> | application.yml with profiles | Consolidate |
| View resolver | <bean class="InternalResourceViewResolver"> | spring.mvc.view.prefix=... property | One-liner |
| Static resources | <mvc:resources mapping=...> | /static, /public auto-served | Move files |
Boot can coexist with XML config. Migrate incrementally:
@Configuration. Test. Repeat.web.xml once DispatcherServlet XML config is gone.Maven:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.x.x</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Keep existing deps; remove spring-webmvc, spring-context — the starter brings them -->
</dependencies>
Remove explicit spring-* versions — let the parent BOM manage them. Version conflicts here are → dependency-resolver territory.
@SpringBootApplication
@ImportResource("classpath:applicationContext.xml") // bridge — delete later
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@ImportResource lets Boot load your old XML. App runs under Boot with zero config migrated. Verify everything works before touching XML.
XML:
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
Boot — option A: explicit @Configuration:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource(@Value("${db.url}") String url,
@Value("${db.user}") String user) {
BasicDataSource ds = new BasicDataSource();
ds.setUrl(url);
ds.setUsername(user);
return ds;
}
// txManager — Boot auto-configures DataSourceTransactionManager if a DataSource bean exists. DELETE.
}
Boot — option B: auto-config (preferred when it applies):
# application.yml
spring:
datasource:
url: ${DB_URL}
username: ${DB_USER}
No Java at all. spring-boot-starter-jdbc sees these properties, auto-configures Hikari (not DBCP — behavior change, flag it).
| XML | Boot |
| -------------------------------------------- | ----------------------------------------------------------- |
| <context:component-scan base-package=...> | @SpringBootApplication scans its own package + subpackages. If your packages are elsewhere: @ComponentScan(basePackages=...) |
| <mvc:annotation-driven/> | Auto — delete |
| <mvc:resources mapping="/static/**" location="/assets/"/> | Move files to src/main/resources/static/ |
| <bean class="...ViewResolver"> | spring.mvc.view.prefix / .suffix properties |
| <tx:annotation-driven/> | Auto — @Transactional just works |
| <context:property-placeholder location=...>| application.yml + @Value or @ConfigurationProperties |
| Filters in web.xml | @Bean FilterRegistrationBean<YourFilter> or just @Component on the filter |
| Servlets in web.xml | @Bean ServletRegistrationBean<...> |
Once every <bean> is migrated: delete @ImportResource, delete applicationContext.xml, delete web.xml. Run tests.
| Gotcha | Symptom | Fix |
| ----------------------------------------- | ------------------------------------------ | ------------------------------------------- |
| Package layout | Beans not found | @SpringBootApplication scans its own package down — move main class up, or add @ComponentScan |
| Auto-config conflict | Two DataSource beans | Your XML defined one, Boot auto-configured another. @Primary, or exclude the auto-config: @SpringBootApplication(exclude=DataSourceAutoConfiguration.class) |
| Connection pool switch | Different perf characteristics | Boot defaults to Hikari. If you need DBCP, declare it explicitly. |
| Context path | URLs all 404 | Was /myapp in the servlet container; now /. Set server.servlet.context-path=/myapp or fix your links. |
| JSP | Whitelabel error page | JSP + embedded Tomcat is fiddly — spring-boot-starter-tomcat provided scope, tomcat-embed-jasper, and keep WAR packaging. Or migrate to Thymeleaf. |
@ImportResource exists so you can do it a bean at a time.javax.* → jakarta.*). Do MVC → Boot 2, then Boot 2 → 3.## Current state
Spring version: <x>
Config style: <XML | JavaConfig | mixed>
Packaging: <WAR on <container>>
## Target
Boot version: <x>
Packaging: <executable JAR>
## Migration steps
| Step | XML removed | Java/YAML added | Test checkpoint |
| ---- | ----------- | --------------- | --------------- |
## Behavior changes
<connection pool, context path, anything auto-config does differently — FLAG THESE>
## Files
### pom.xml (diff)
### Application.java (new)
### application.yml (new)
### Deleted: <web.xml, applicationContext.xml, ...>
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.