Troubleshooting
Duplicate Feign client bean
Two Feign interfaces pointing at the same target service fail at startup:
Description:
The bean 'optimization-user.FeignClientSpecification', defined in null, could not
be registered. A bean with that name has already been defined in null and
overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting
spring.main.allow-bean-definition-overriding=true
Each @FeignClient registers a configuration bean named after the client. The
name comes from getClientName(), which returns the value/name attribute —
so two interfaces naming the same service collide.
Give each interface its own contextId:
@FeignClient(name = "optimization-user", contextId = "userQueryClient")
public interface UserQueryClient { /* ... */ }
@FeignClient(name = "optimization-user", contextId = "userCommandClient")
public interface UserCommandClient { /* ... */ }
contextId overrides the name used for bean registration while leaving service
discovery pointed at name, so both interfaces still resolve to the same
service.
The suggested alternative, spring.main.allow-bean-definition-overriding=true,
does make the message go away — by silently letting one configuration replace
the other, application-wide, for every bean. That masks genuine duplicate-bean
bugs elsewhere. Use contextId.
Property name reported as unknown
'xxx.yyy.ZZZ' is an unknown property. Did you mean 'xxx.yyy.ZZZ'
The suggestion looks identical to what you wrote because the only difference is case. Configuration property names must be lower-case kebab-case:
# Wrong
app.myService.maxRetryCount=3
# Right
app.my-service.max-retry-count=3
Relaxed binding maps max-retry-count onto a maxRetryCount field
automatically, so the Java side keeps camelCase. Only the properties file has to
be kebab-case.
InvocationException in the target VM
com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method
The debugger raised this while evaluating a variable in a watch or inspection
window — it called toString() on an object and that call threw.
Most often the entity's toString() walks a lazily-loaded association outside
an active session, or a mapping is wrong and the getter throws. Check the entity
mapping, and exclude lazy associations from toString():
@ToString(exclude = {"orders"}) // Lombok
The exception is a symptom of the debugger, not of the application logic — the same code may run correctly when not being inspected.
GET request fires after a POST
After a POST completes, a GET is issued automatically with the POST parameters appended to the URL.
The request body was sent as multipart/form-data or
application/x-www-form-urlencoded where the handler expected JSON, so the
browser treated it as a normal form submission and followed the response.
Check the request's Content-Type and the handler's consumes. For a JSON API
both should be application/json, and the handler should take @RequestBody
rather than @RequestParam. See REST API design.
A redirect response (3xx) from a POST also produces a follow-up GET — that is the POST/redirect/GET pattern, and it is correct for HTML forms but wrong for a JSON API, which should return the status directly.
Removed OAuth2 annotations
@EnableAuthorizationServer // no longer exists
@EnableResourceServer // no longer exists
The spring-security-oauth2 project reached end of life; these annotations are
gone rather than deprecated. Replacements:
| Old | New |
|---|---|
@EnableAuthorizationServer | Spring Authorization Server |
@EnableResourceServer | spring-boot-starter-oauth2-resource-server and oauth2ResourceServer(...) |
@EnableOAuth2Sso | spring-boot-starter-oauth2-client and oauth2Login(...) |
This is a rewrite of the security configuration, not a dependency bump. Budget accordingly when planning the upgrade.
Removed Spring Security 6 APIs
Code written against Spring Security 5 will not compile:
| Removed | Replacement |
|---|---|
WebSecurityConfigurerAdapter | A SecurityFilterChain bean |
authorizeRequests() | authorizeHttpRequests() |
antMatchers(), mvcMatchers() | requestMatchers() |
.and() chaining | Lambda DSL |
.apply(configurer) | .with(configurer, customizer) |
See Spring Security for the current form.
Startup fails with no obvious cause
java -jar app.jar --debug
--debug prints the condition evaluation report, showing which auto
configurations matched and — more useful — which did not, and why. A missing
datasource, an absent driver on the classpath or a property that never bound
are all visible there.
For dependency problems specifically:
mvn dependency:tree
./gradlew dependencies --configuration runtimeClasspath