5

I am writing a batch using Spring Boot 2.7.1 and spring-boot-starter-batch . The batch needs 2 different WebClient to call 2 different APIs with different authentication systems, that I configure through standard Spring Boot properties (spring.security.oauth2.client etc).

It works well, but I realized the batch was listening on port 8080 when running, because I have imported spring-boot-starter-web , which enables the auto-configuration of my WebClient , by injecting a ClientRegistrationRepository . It's not a major issue, but it prevents me from launching the batch twice in parallel for instance, because the port is already used... so I would like to disable the web server part.

The problem is that when I disable the web server, either through properties, code or dependencies (by removing spring-boot-starter-web), then the batch doesn't start anymore, because ClientRegistrationRepository is not loaded anymore, because I require

a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found

This is because, there's a conditional on Spring's OAuth2ClientAutoConfiguration :

@AutoConfiguration(before = SecurityAutoConfiguration.class)
@ConditionalOnClass({ EnableWebSecurity.class, ClientRegistration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@Import({ OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class })
public class OAuth2ClientAutoConfiguration {

}

Because the application is not of type SERVLET, but NONE, this doesn't get enabled.

I've tried to "force load" it :

@ImportAutoConfiguration(OAuth2ClientAutoConfiguration.class)

but it doesn't work.

Looking into the source code, I see that OAuth2ClientAutoConfiguration is actually loading 2 config classes, but they are not public, so I can't import them directly :

@Import({ OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class })

there must be a trick to achieve that.. but what is it ?

Vincent F
  • 6,523
  • 7
  • 37
  • 79
  • You have disable the web server using properties means you have used `spring.main.web-application-type=NONE` and your batch application wont start if you add this property? – Rishal Jul 29 '22 at 08:38
  • yes, it doesn't start, because the batch still needs to have webClient properly configured (to call remote APIs), but ClientRegistrationRepository is missing and batch fails to start – Vincent F Jul 29 '22 at 09:14
  • 1
    Including the `spring.main.web-application-type=NONE` doesnt exclude the web libraries, can you share the logs by setting the log level to trace. – Rishal Jul 29 '22 at 09:20
  • I have updated the question, showing why OAuth2ClientAutoConfiguration doesn't get enabled when the application type is NONE : the binary is here, but it's explicitly not enabled because of that. – Vincent F Jul 29 '22 at 09:39

1 Answers1

0

With Spring Boot, you can customize the port of your webapplication by setting the property server.port=8095 in your application.properties or any customized env properties file ie application-dev.properties, application-prod.properties and so on.

Using these property, your webapplication will listen on the port of your choice and will not conflict anymore with other stuff. And if you need multiple instances running in parallel, run them with a range of ports could be great (@see https://stackoverflow.com/a/56884100/390462. You can add listeners too (@see https://stackoverflow.com/a/51876661/390462). Or at least multiple instances of your batch application with differents server.port values.

If you want to disable the webserver, the best bet is to use the property : spring.main.web-application-type=none.

I've just found something interesting using AuthorizedClientServiceOAuth2AuthorizedClientManager in your service layer (@see https://stackoverflow.com/a/60173451/390462

BendaThierry.com
  • 2,080
  • 1
  • 15
  • 17
  • 1
    but instead of changing the server.port, the more logical thing would be to not run the server at all, which is what I am trying to do – Vincent F Jul 29 '22 at 09:12
  • Using `spring.main.web-application-type=none` could do the job then. – BendaThierry.com Jul 29 '22 at 09:37
  • Just see your edit now, did you try to create a custom annotation without these conditionnal statment and call your class with it ? – BendaThierry.com Jul 29 '22 at 09:43
  • 2
    since the actual Configuration classes are not public, I would also need to copy paste them... I can try that, but I may end up copy pasting more things, and it definitely looks like a hack, not very "SpringBoot-ish" – Vincent F Jul 29 '22 at 09:45
  • The web security layer is required for oauth anyway, so servlet dependencies are mandatory. It seems to be a wrong way to go with custom annotation. If I were you, I will go for a working way now (the first way I suggested), and seek a better solution in the background. – BendaThierry.com Jul 29 '22 at 09:47
  • 1
    that's what I am doing ;-) I am just surprised to be the first one having the issue ;-) – Vincent F Jul 29 '22 at 09:54
  • I've just found something interesting in service layer with oauth. Answer updated with it. – BendaThierry.com Jul 29 '22 at 09:55
  • Okay, maybe you are the first one to talk about it here, maybe not ;) It didn't use OAuth to run any batch applications without the web layer, so it is new here ;) But I have worked on many projects where batch were done with some schedulers impl with or without cron task to do them with hundreds of To of datas. Hope you'll find a way. – BendaThierry.com Jul 29 '22 at 10:01