Spring WebClient without the springboot-starter-web-flux - spring

Mine is a Spring boot application, but doesnt uses any web-feature. It's just used as a command-line app that will be triggered by a CRON in a scheduled interval and then it performs the job and die (is not ever running web app)
In this Job, I would need to make a REST call and would need to use WebClient for the same. Below is my dependency i use to bring in the WebClient
implementation 'org.springframework.boot:spring-boot-starter-webflux'
But this dependency keeps my app running and doesnt allow the job to die once the job is done. I tried excluding netty from the above dependency, but that is resulting in the below error
Caused by: org.springframework.context.ApplicationContextException: Unable to start ReactiveWebApplicationContext due to missing ReactiveWebServerFactory bean.
How to use WebClient and at the same time not to use any Web features ?
Note: I tried giving spring.main.web-application-type=none in my property file and it is helping me to exclude web-feature. But is that the only way ?

It’s not the only way but I think it’s certainly the easiest.
You could manually configure the type of application context that’s used and exclude some auto-configuration classes, but setting the web-application-type property or configuring it programmatically on SpringApplication or SpringApplicationBuilder will achieve the same result with less code and configuration.

Related

Difference Between Spring MockMvcBuilders.standaloneSetup and WebMvcTest

I have a Spring Boot 2.6.0 application that depends on libraries which use fields initialised with SpEL syntax, e.g.
#Value("${some.value.in.library}") aField;
I attempted to write a Spring MVC test for a controller with #WebMvcTest. However I kept getting failed to load applicationcontext errors due to a SpELEvaluationException for the fields mentioned above.
Even after trying many, many, different test annotations such as #ConfigurationProperties and other fixes. I could see the properties that are defined in application-test.yml being loaded in the startup logs but they were not getting injected into the class.
Finally, I tried using:
MockMvcBuilders.standaloneSetup
and the test was able to start and run successfully.
Unfortunately, due to the complexity of the application and the use of a library where the problem occurs, it is difficult to create a minimal reproducable example.
So my question is, why does MockMvcBuilders.standaloneSetup work, whereas #MockMvcTest doesn't?
This answer suggests that #MockMvcTest should not load the full application context. But that does not seem to be the case based on the failed to load applicationcontext errors.

Can we invoke a method in spring in case the application start fails

I have situation where I need to perform certain tasks in case my springboot applications fails to start. Basically I want to release various resources. I tried using #PreDestroy annotation but it did not work as application was not started yet. Is there any way out by which we can perform few actions in case springboot application fails to start
Spring app heavily using threadpool context when start the program , so when the main program fail spring can not manage the standard beans related to spring. you can only start new thread using implements Runnable in main class and no access to spring resources as well , just simple getclassloader().getresourceasstream is available there .
However you can write independence java Agent using -javaagent to do some operation on release resource ,see java.lang.instrument.Instrumentation;

Spring Integration Invoking Spring Batch

Just looking for some information if others have solved this pattern. I want to use Spring Integration and Spring Batch together. Both of these are SpringBoot applications and ideally I'd like to keep them and their respective configuration separated, so they are both their own executable jar. I'm having problems executing them in their own process space and I believe I want, unless someone can convince me otherwise, each to run like they are their own Spring Boot app and initialize themselves with their own profiles and properties. What I'm having trouble with though is the invocation of the job in my SpringBatch project from my SpringIntegration project. At first I couldn't get the properties loaded from the batch project, so I realized I need to pass the spring.active.profiles as a Job Parameter and that seemed to solve that. But there are other things in the Spring Boot Batch application that aren't loading correctly like the schema-platform.sql file and the database isn't getting initialized, etc.
On this initial launch of the job I might want the response to go back to Spring Integration for some messaging on Job Status. There might be times when I want to run a job without Spring Integration kicking off the job, but still take advantage of sending statuses back to the Spring Integration project providing its listening on a channel or something.
I've reviewed quite a few Spring samples and have yet to find my exact scenario, most are with the two dependencies in the same project, so maybe I'm doing something that's not possible, but I'm sure I'm just missing a little something in the Spring configuration.
My questions/issues are:
I don't want the Spring Integration project to know anything about the SpringBatch configuration other than the job its kicking off. I have found a good way to do that reference to the Job Bean without getting my entire batch configuration loading.
Should I keep these two projects separated or would it be better to combine them since I have two-way communication between both.
How should the Job be launch from the integration project. We're using the spring-batch-integration project with JobLaunchRequest and JobLauncher. This seems to run it in the same process as the Spring Integration project and I'm missing a lot of my SpringBootBatch projects initialization
Should I be using a CommandLineRunner instead to force it to another process.
Is SpringApplication.run(BatchConfiguration.class) the answer?
Looking for some general project configuration setup to meet these requirements.
Spring Cloud Data Flow in combination with Spring Cloud Task does exactly what you're asking. It launches Spring Cloud Task applications (which can contain batch jobs) as new processes on the platform you choose. I'd encourage you to check out that project here: http://cloud.spring.io/spring-cloud-dataflow/

Programmatically configure Spring Boot app

what's the easiest way to get the spring boot goodness but not try to autoconfigure all the things? For instance, to only run flyway with our already configured properties (some loaded via Consul + Spring Cloud), I was hoping I could do something like:
#Configuration
#Import({DataSourceAutoConfiguration.class, FlywayAutoConfiguration.class})
public class FlywaySetup {}
and have the main method just call SpringApplication.run(FlywaySetup.class)
The problem with this is it picks up all the Component Scan / crazy long list of other dependencies. Any way to specifically configure the dependencies (but still get the nicities of the framework)
If you run this app, it shouldn't use component scan at all. There's nothing that triggers component scan in spring boot besides #ComponentScan (that's available on #SpringBootApplication).
It would help if you could provide more accurate details rather than "crazy long list of other dependencies.". Running that FlywaySetup should only load those two configuration classes (important: these are not handled as auto-configuration anymore). If you have component scan, there's something else you're not showing.
You can exclude auto-configurations you don't need.
You may want to take a look at this SO answer to explore mechanism how to do that.

tomcat: guvnor & webservice load order

I have guvnor deployed on tomcat 7. Now need to deploy a wrapper webservice around the BRMS. The webservice is a spring-ws and uses #Autowired kbase dependency injection. kbase is configured in spring-context XML as (not literal):
<drools:resource id="xxx" source="http://localhost:8080/guvnor/.../<package>/LATEST
Now the problem is tomcat first loads the webservice which fails to initialize as the guvnor URL is not up yet.
I can work around this by first starting only guvnor along with tomcat startup and then copy the WS war to the webapps folder. This works but is painful to do everytime.
What is the best approach?
I have seen this thread, but not sure if it will work in this context: Is there a way to enforce a deployment order in tomcat6?
Tried the following ways to address this:
Tomcat brings up both services on starup. The initialization of webservice fails but bring up the webservice manually through tomcate admin interface.
Use a script to do the same as above to bring up the webservice after a delay.
Change the drools package initialization to load through drools API instead of through config files along with a retry logic.
All of these work, but retaining the last option in the production code.

Resources