PF4J Spring - not able to load any components in the plugin other than the beans declared in configuration class - spring-boot

We are using plugin architecture for one of our projects and we decided to use Spring pf4j for the same.
When we load the plugin via extensions - the application context is not able to find the beans created using #component in the plugin project- but the beans declared in #configuration classes are injected properly when we configure the plugin using register method - Is there anyway to scan and load the spring components in the plugin?

#Component in plugin is registered to main ApplicationContext via SpringExtensionFactory, make sure you set it up correctly in DefaultPluginManager correctly.
If you are going to use pf4j in SpringBoot, I would suggest you take a look sbp project. It is built upon pf4j and provides better integration with SpringBoot.

Related

what does "spring-kafka without springboot" mean

I'm totally new to Kafka and terribly confused by this:
https://docs.spring.io/spring-kafka/reference/html/#with-java-configuration-no-spring-boot
I don't understand what that even means. What does "no spring boot mean" because that example sure as hell uses spring boot. I'm so confused....
EDIT
if I'm using SpringBoot and spring-kafka, should I have to manually create #Bean ConcurrentKafkaListenerContainerFactory as shown here. Most of the examples in the docs for setting up filtering / config / etc seem to use the "manual" configuration using #Bean. Is that "normal"? The docs are very confusing to me...especially this warning:
Spring for Apache Kafka is designed to be used in a Spring Application Context. For example, if you create the listener container yourself outside of a Spring context, not all functions will work unless you satisfy all of the …​Aware interfaces that the container implements.
It's referring to the autowired configuration, as compared to putting each property in the config via HashMap/Properties in-code.
Also, it does not use #SpringBootApplication or SpringApplication.run, it just calls a regular main method using a hard-coded Config class.
Spring boot contains the functionality of AutoConfiguration
What this means is that spring boot when discovers some specific jar dependencies it knows, in the project, it automatically configures them to work on a basic level. This does not exist in simple Spring project where even if you add the dependency you have to also provide the configuration as to how it should work in your application.
This is also happening here with dependencies of Kafka. Therefore the documentation explains what more you have to configure if you don't have spring-boot with auto-configuration to make kafka work in a spring project.
Another question asked in comment is what happens in case you want some complex custom configuration instead of the automatic configuration provided while you are in a spring-boot app.
As documented
Auto-configuration tries to be as intelligent as possible and will
back-away as you define more of your own configuration. You can always
manually exclude() any configuration that you never want to apply (use
excludeName() if you don't have access to them). You can also exclude
them via the spring.autoconfigure.exclude property.
So if you want to have some complex configuration which is not automatically provided by spring-boot through some other mechanism like a spring-boot specific application property, then you can make your own configuration with your custom bean and then either automatic configuration from spring-boot for that class will back of as spring does several intelligent checks during application context set up or you will have to exclude the class from auto configuration manually.
In that case you could probably take as an example reference of how to register manually your complex configurations in spring boot what is documented on how to be done in non spring boot app. doc

How to selectively make one class to be the code that should be run in Spring (Spring Boot 2.x)

We have several classes annotated with the #Component notation in our Spring Boot 2.x project - but we would like to selectively pick only one of these class at runtime.
To further elaborate we created a Uber Jar - which will run on several machines - but each jar should be running a different logic and this logic is dictated by one of this class.
What is the cleanest way to achieve this in Spring boot 2.x? I read something about profiles etc. any cleaner solutions are very much appreciated.
Use the Spring Boot Maven plugin, and configure it to use the PropertiesLauncher, then set the loader.main via the command line. Or, you can specify the whole thing via the command line. Assuming you're using the Maven (or Gradle) Spring Boot plugin to build the jar/war file:
java -cp bootApp.jar -Dloader.main=org.your.package.DemoApplication org.springframework.boot.loader.PropertiesLauncher
You can group and move those #Component classes in multiple #Configuration classes. In this case you have to manually declare them as #Beans (methods). You will define as many #Configuration classes as your machines count.
Further on, you can enable or disable configuration classes by means of Spring Profiles. Profiles are enabled using spring.profiles.active system property (-Dspring.profiles.active=profile1,profile2).
If you want to have it clean then you have to do it in 'Dependency Inversion Principle' way: You should define interfaces for your #Components and each #Configuration will declare #Beans of a concrete type. In this way you can use #Autowired dependency injection w/o knowing the concrete implementation.

Prevent SpringBoot from creating an EmbeddedServletContainer

I'm trying to convert an existing spring application into a spring boot application. this application is not a web application but somewhere deep in it's maven dependencies hierarchy it includes a spring-web jar and therefore spring-boot tries to autoconfigure a WebEnvironment and in turn complains about not finding an EmbeddedServletContainerFactory. But this is intended as I'm using spring-boot-starter instead of spring-boot-starter-web.
My questing is: how can I prevent spring-boot from autodiscovering web specific items in the classpath? I already tried something like
#EnableAutoConfiguration(exclude = { EmbeddedServletContainerAutoConfiguration.class })
but it doesn't seem to work. Debugging the startup process I see that it runs into a method called deduceWebEnvironment() which is called unconditionally. This method returns true as soon as the following classes are on the classpath:
javax.servlet.Servlet, org.springframework.web.context.ConfigurableWebApplicationContext
But again, even this classes exist in the cp, I don't want to startup a web-application.
Try new SpringApplicationBuilder(YourApp.class).setWebEnvironment(false).run(args) You can also disable the web mode via configuration in application.properties
spring.main.web-environment=false
See the documentation

Initialize Spring Application Context for spring projects packaged as a jar

We have several java projects. Most of them are built with Struts 2.0 framework and few built with Spring 3.2. We want to consolidate all the back-end integration service into a separate project using spring 3.2 and import this jar file on all the projects. Here are my questions
What is the best way to initialize spring application-context for a jar based spring project? This jar is utilized by multiple web-project that are built using Struts and other non spring MVC frameworks.
I read How to package spring based library for reuse?. However, this question didn't answer on how to auto-load the application context when you a call a Service from the built spring-example.jar file.
For example. I have a WeatherService.java class in spring-framework.jar file. I want to import the spring-framework.jar file into another Struts-MVC based application and call WeatherService.java from an Action Class. I want the spring bean configuration to initiate automatically when calling the WeatherService.
You can use #Import annotation if using Java configurations or <import> tag if using XMl configs. With this approach you can reuse import one Spring context into another one.
Link to documentation:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-using-import
EDIT:
If you are using maven, place your application-context.xml into src/main/resources. If not, make sure that it's on classpath.
Than if you are using XML config do
<import resource="classpath:application-config.xml"/>
or if you are using Java config do
#ImportResource("classpath:application-config.xml")

FileNotFoundException in a testing a Maven module

I'm working on a recently mavenized legacy project with following multi-modular structure:
Parent:
Web
Service
Dao
("Service" module is dependent on "Dao" module)
Problem: some tests of Service classes call DAO code that creates beans using Spring's ClassPathXmlApplicationContext (this part is not really DAOs but caching related). Since, ClassPathXmlApplicationContext uses spring config xml of the DAO module - the Service tests fail throwing FileNotFoundException. I think this is because tests run in Service module and the spring config xml being referred lies in Dao module.
Please advise on how can I resolve the above issue in tests referring to code/resources of other modules?
Put a copy of the Spring configuration under src/test/resources in the Service module. Quite often you want a different configuration for testing anyway, but also it means your tests are less dependent on configuration changes in another module.

Resources