Skip to main content

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:

OldNew
@EnableAuthorizationServerSpring Authorization Server
@EnableResourceServerspring-boot-starter-oauth2-resource-server and oauth2ResourceServer(...)
@EnableOAuth2Ssospring-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:

RemovedReplacement
WebSecurityConfigurerAdapterA SecurityFilterChain bean
authorizeRequests()authorizeHttpRequests()
antMatchers(), mvcMatchers()requestMatchers()
.and() chainingLambda 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